1. 程式人生 > 其它 >Java(7)面向物件——繼承性、方法的重寫、super關鍵字、修飾符小結、子類物件例項化過程、程式碼塊、內部類

Java(7)面向物件——繼承性、方法的重寫、super關鍵字、修飾符小結、子類物件例項化過程、程式碼塊、內部類

技術標籤:java面向物件程式設計

目錄

繼承性

  1. 繼承性格式:class A extends B{語句;}——稱A為子類、派生類、subclass,B為父類、超類、基類、superclass,一個子類只能繼承一個父類,一個父類可以有多個子類;
  2. B是A的直接父類,B的父類是A的間接父類,A繼承了直接父類B和所有間接父類的所有屬性和方法,對於B中的private修飾的屬性或方法,A同樣繼承了,只不過不能直接呼叫而已;
  3. A除了繼承父類的屬性和方法,還可以宣告自己特有的屬性和方法,也可以過載父類的方法,還可以重寫父類的方法;
  4. 如果沒有顯示地宣告一個父類,那麼該類繼承java.lang.Object類,除java.lang.Object類的類都直接或間接繼承於java.lang.Object類,所以所有的類都繼承了java.lang.Object類的方法;
  5. 繼承性的好處在於增強程式碼的複用性和程式碼功能的擴充套件性,為多型性提供了前提;

方法的重寫

子類可對繼承於父類的方法進行重寫,從而覆蓋父類的方法,子類重寫父類的方法要求:

  1. 子類重寫的方法名和引數列表與父類被重寫的方法名和引數列表相同;
  2. 子類重寫的方法的修飾符不小於父類被重寫的修飾符(子類不可重寫父類中宣告為private的方法);
  3. 返回值型別要求:父類被重寫的方法返回值型別為void時,子類重寫的方法返回值也必須為void;父類被重寫的方法返回值型別為A類,那麼子類重寫的方法返回值型別為A類或A類的子類;父類被重寫方法的返回值型別為基本資料型別,子類重寫的方法返回值型別須與父類相同;
  4. 子類重寫的方法丟擲的異常型別不大於父類被重寫的方法丟擲的異常型別;
  5. 父類的方法如果不用static修飾,那麼子類可重寫該方法,且重寫的方法不能用static修飾;父類中用static修飾的方法,子類的同名方法也要有static修飾,但這是不構成重寫;
    示例程式碼如下:
public class A extends B{
    public StringBuffer str1;
    public int getA(int a){
        System.out.println("這是過載的getA方法");
        return a;
    }
    public
void setA(int a){ System.out.println("這是重寫成功setA方法"); } } class B { private int a; double b; protected byte c; public char d; public void setA(int a){ this.a = a; System.out.println("這是B的setA方法"); } public int getA(){ System.out.println("這是B的getA方法"); return a; } public B(){ System.out.println("B的無參構造器"); } public B(char e){ d = e; System.out.println("B的有參構造器"); } }

測試上述的派生類A:

public class ThePerson1 {
    @Test
    public void Test3(){
        A a = new A();
        a.getA();  //getA未重寫
        a.setA(5);  //重寫了setA方法
        a.getA(10);  //過載了setA方法
    }
}

super關鍵字

super關鍵字用於訪問父類的屬性、方法和構造器,實際上使用this關鍵字或預設也可以追溯呼叫父類的屬性和方法,但如果子類重寫了父類的方法,則必須指明super關鍵字才能呼叫父類被過載的方法。
super關鍵呼叫構造器時注意:

  1. 如果子類的構造器未顯示用super呼叫父類構造器,則預設呼叫父類無參構造器;
  2. 如果子類要呼叫父類指定構造器,需用super(形參列表); 顯示地呼叫;
  3. 子類構造器中this(形參列表);和super(形參列表);只能二選一,且放在首行;
    示例程式碼如下:
public class A extends B{
    public A(){
        System.out.println("A中的空參構造器");
    }
    public A(int a){
        super(12);
        System.out.println("A中的int a構造器");
    }
    public A(char a){
        super('9');
        System.out.println("A中的char a構造器");
    }
}

class B {
    private int a;
    public char d;

    public B(){
        System.out.println("B的無參構造器");
    }
    public B(char e){
        d = e;
        System.out.println("B的char e有參構造器");
    }
    public B(int e){
        a = e;
        System.out.println("B的int e有參構造器");
    }
}

測試派生類A的物件建立過程程式碼如下;

import faceDuiXiang.Person;
import org.junit.Test;
public class ThePerson1 {
    @Test
    public void test3(){
        A a1 = new A();
        A a2 = new A(2);
        A a3 = new A('a');
    }
}

修飾符小結

許可權修飾符:

  • Java許可權修飾符public、protected、(預設)、private置於類的成員定義前,用來限定物件對該類成員的訪問許可權。
  • 對於class的許可權修飾只可以用public和default(預設),public類可以在任意地方被訪問,default類只可以被同一個包內部的類訪問。

static修飾符:

  • static用於修飾類的成員變數和成員方法以及程式碼塊和內部類,用static修飾的類成員隨著類的載入而載入,被類以及類的所有例項共享,如果一個物件修改了某個靜態變數,那麼其他物件呼叫此變數會得到修改的結果;
  • 類可以調研靜態屬性和方法,但不能呼叫非靜態屬性和方法,且靜態方法的方法體內不能有this和super關鍵字,這表明this和super關鍵字只能用於代表物件,不能直接代表類;
  • 物件既可以呼叫非靜態屬性和方法,又可以呼叫靜態屬性和方法;
  • 開發時,多個物件共享的變數以及類中的常量一般用static宣告為靜態;
  • 操作靜態屬性的方法以及開發工具類的方法,一般要用static宣告為靜態方法;

final修飾符:

final可以修飾類、成員變數、區域性變數、方法;

  • final修飾的類不可被繼承;
  • final修飾的方法不能被重寫;
  • final修飾的變數相當於常量,對於成員常量,可以顯示初始化、在程式碼塊中初始化或構造器初始化,對於區域性常量,可以顯式初始化和傳入實參時初始化;
  • static final修飾的成員變數為全域性常量;

子類物件例項化過程

  1. 構造某個類的物件,根據傳入的引數確定構造器;
  2. 構造器的形參得到了實參的值,然後執行第一行程式碼;
  3. 如果這個類不是java.lang.Object,進入第5步;
  4. 如果這個類是java.lang.Object,執行當前構造方法中的程式碼,再依次執行直接子類的程式碼,直到目標類,構造過程完成;
  5. 第一行程式碼如果不是this(引數列表)或super(引數列表),系統會預設呼叫直接父類的空參構造器;
  6. 第一行程式碼如果是this(引數列表),則呼叫同一個類中相應的構造器,回到第2步;
  7. 第一行程式碼如果是super(引數列表),則呼叫父類指定的構造器,回到第2步;

程式碼塊

程式碼塊可以被static修飾,分為靜態程式碼塊和非靜態程式碼塊,用於初始化類和物件。
靜態程式碼塊:
靜態程式碼塊隨著類的載入而載入,只執行一次;
如果有多個程式碼塊,按照先後順序執行;
可以呼叫靜態屬性和方法,不能呼叫非靜態屬性和方法,可以有輸出語句;
非靜態程式碼塊:
非靜態程式碼塊隨著物件的建立而執行,多個非靜態程式碼塊按照先後順序依次執行;
非靜態程式碼塊先於構造器執行,就是說建立物件時,先執行程式碼塊,再執行構造器;
非靜態程式碼塊既可以呼叫靜態的屬性和方法,又可以呼叫非靜態的屬性和方法;
示例程式碼:

public class A extends B{
    public A(){
        System.out.println("A中的空參構造器");
    }
    public A(int a){
        super(12);
        System.out.println("A中的int a構造器");
    }
    public A(char a){
        super('9');
        System.out.println("A中的char a構造器");
    }
    {
        System.out.println("程式碼塊1");
    }
    {
        System.out.println("程式碼塊2");
    }
}

class B {
    private int a;
    public char d;
    public B(){
        System.out.println("B的無參構造器");
    }
    public B(char e){
        d = e;
        System.out.println("B的char e有參構造器");
    }
    public B(int e){
        a = e;
        System.out.println("B的int e有參構造器");
    }
}
public class ThePerson1 {
    @Test
    public void test3(){
        A a2 = new A(2);
    }
}

程式碼執行結果為:
在這裡插入圖片描述
程式碼執行結果表明,建立物件時,先一層層執行this(引數列表)或super(引數列表)知道根父類,然後一次執行每個類的程式碼塊和構造器內程式碼。

內部類

成員內部類:

  • 內部類不能與外部類同名,成員內部類可以被各種許可權修飾符和static以及final修飾;
  • 靜態成員內部類可以呼叫外部類的靜態屬性和方法,而不能呼叫外部類的非靜態屬性和方法;
  • 非靜態成員內部類既可以呼叫外部類的靜態屬性和方法,又可以呼叫外部類的非靜態屬性和方法;
  • 非靜態的成員內部類中不能宣告靜態成員,靜態成員只能存在於外部類或靜態內部類;
  • 外部類呼叫內部類的成員,需用“內部類.成員”或“內部類的例項.成員”的方式,外部類可以呼叫內部類的私有成員;
  • 成員內部類可直接呼叫外部類的成員,包括私有成員;

區域性內部類:

  • 區域性內部類聲明於方法或程式碼塊內,只能由方法或程式碼塊使用;
  • 區域性內部類可以直接使用所有外部類的成員,包括私有的;
  • 區域性內部類可以使用外部方法中被final修飾的區域性變數;
  • 區域性內部類作為區域性的一份子,不能被static修飾,因此區域性內部類不能包含靜態成員;

匿名內部類:

  • 匿名內部類不能定義任何靜態成員、方法和類,只能建立匿名內部類的一 個例項。一個匿名內部類一定是在new的後面,用其隱含實現一個介面或
    實現一個類。
  • 宣告格式:
  • java new 父類構造器(實參列表)|實現介面(){ //匿名類類體; }
  • 匿名內部類必須繼承父類或實現介面;
  • 匿名內部類只能有一個物件;
  • 匿名內部類物件只能使用多型形式引用;