B 類 對象 繼承 多態與動態綁定

1 .java文件與.class文件

Java中所有的方法,屬性都必須以類的形式存在。也就是說,他們必須是類的成員。以Employee類爲例,java的源文件名稱爲Employee.java,在這個源文件中,只能有一個public類,且它的名字爲Employee。在一個Java源文件中,只能有一個公有類,但可以有任意數目的非公有類。在編譯以後,每一個類將被編譯成一個.class文件。


2 類的概念

類是一種抽象的概念,對象是類的一種具體表示形式,是具體的概念。先有類,然後由類來生成對象(Object)。對象又叫做實例(Instance)。


3值傳遞

在Java中進行方法的參數傳遞時,無論傳遞的是原生數據類型還是引用類型,參數傳遞方式統一是傳值(pass by value)。Java中沒有傳引用(pass by reference)的概念。

在引用傳遞的時候,傳遞的是地址的值。如果在方法中,改變了傳遞的地址的值,那將會毫無變化。下面代碼可以很好的解釋這個問題

class Point
{
    int x;
    int y;
}
public class Test
{
    
    public void changeOne(Point point)
    {
        point.x=3;
        point.y=4;
    }
    public void changeTwo(Point point)
    {
        point=new Point();
        point.x=3;
        point.y=4;
    }
    public static void main(String[] args)
    {
        Test test=new Test();
        Point point=new Point();
        /*test.changeOne(point);*/
        test.changeTwo(point);
        System.out.println(point.x);
        System.out.println(point.y);
    }

}
因此,在Java中 ,方法參數的使用情況如下

  • 一個方法不能修改一個基本數據類型的參數的。
  • 一個方法可以改變一個對象參數的狀態
  • 一個方法不能讓對象參數引用一個新的對象

4 重載

表示兩個或多個方法名字相同,但方法參數不同。方法參數不同有兩層含義:

  • 參數個數不同。
  • 參數類型不同。

對於構造方法重載:只需看參數即可。如果想在一個構造方法中調用另外一個構造方法,那麼可以使用this()的方式調用,this()括號中的參數表示目標構造方法的參數。this()必須要作爲構造方法的第一條語句,換句話說,this()之前不能有任何可執行的代碼。

注意:方法的返回值對重載沒有任何影響。方法的名字和參數列表稱爲方法的簽名



5 繼承

  • Java是單繼承的,意味着一個類只能從另一個類繼承(被繼承的類叫做父類【基類,base class】, 繼承的類叫做子類),Java中的繼承使用extends關鍵字。
  • 當生成子類對象時,Java默認首先調用父類的不帶參數的構造方法然後執行該構造方法,生成父類的對象。接下來,再去調用子類的構造方法,生成子類的對象。【要想生成子類的對象,首先需要生成父類的對象,沒有父類對象就沒有子類對象。比如說:沒有父親,就沒有孩子】。
  • 需要使用super()顯式調用父類構造方法
  • super關鍵字:super表示對父類對象的引用。super跟this不一樣,不能將super賦給另一個對象變量,它只能指示編譯器調用超類的方法。
  • 如果子類使用super()顯式調用父類的某個構造方法,那麼在執行的時候就會尋找與super()所對應的構造方法而不會再去尋找父類的不帶參數的構造方法。與this一樣,super也必須要作爲構造方法的第一條執行語句,前面不能有其他可執行語句。因爲沒有父親,就沒有兒子
  • 關於繼承父類公有的,子類也有,父類沒有的,子類可以增加,父類有的,子類可以改變
  • 繼承時生成父對象與子對象兩個對象,內存地址相連,引用指向子類。
  • 構造方法不能被繼承
  • 方法和屬性可以被繼承子類的構造方法隱式地調用父類的不帶參數的構造方法
  • 當父類沒有不帶參數的構造方法時,子類需要使用super來顯式地調用父類的構造方法,super指的是對父類的引用。如果父類沒有不帶參數的構造方法,而子類又沒有顯示地調用父類的構造方法,那麼編譯器將報錯。因爲編譯器只能幫你調用不帶參數的構造方法。


6 構造塊與靜態塊

對於初始化數據域的方法,除了在構造器中賦值以及在聲明中賦值以後,還有一種方式,就是使用構造塊。在一個類中,可以含有多個構造塊,且構造塊在每次類的初始化的時候,都會被執行而靜態塊只會被執行一次。對於繼承關係,在初始化子類的時候,它們的執行順序如下

父類靜態塊-》子類靜態塊-》父類構造塊-》子類構造塊。


7 重寫

方法重寫(Override):又叫做覆寫,子類與父類的方法返回類型一樣、方法名稱一樣,參數一樣,這樣我們說子類與父類的方法構成了重寫關係。這種關係只會發生在父子類之間。

當兩個方法形成重寫關係時,可以在子類方法中通過super.run()形式調用父類的run()方法,其中super.run()不必放在第一行語句,因此此時父類對象已經構造完畢,先調用父類的run()方法還是先調用子類的run()方法是根據程序的邏輯決定的。

在覆蓋一個方法時,子類的方法不能低於超類的方法可見性。

8 多態

一個對象可以指示多種實際類型的現象稱爲多態。在運行時能夠自動地選擇調用哪個方法的現象稱爲動態綁定。

可以理解爲父類型的引用可以指向子類的對象。最常用的,面向接口的編程。接口聲明的變量指向其實現類的實例。

有一個規則可以用來判斷是否爲繼承關係,就是“is -a”規則,即子類每個對象也是父類的每個對象。在程序中任何出現超類對象的地方,都可以用子類進行替代,這又叫“置換法則”。


動態綁定

Java中,方法的的調用執行以下過程

(1) 編譯器查看對象的聲明類型和方法名。假設調用x.f(param),且隱式參數x聲明爲C類的對象。編譯器會一一列舉所有C類名爲f的方法和其超類中訪問屬性爲public且名爲f的方法。至此,編譯器已獲得所有可能被調用的候選方法

(2)接下來,編譯器將查看調用方法時提供的參數類型。如果在所有名爲f的方法中存在一個與提供的參數類型完全匹配,就選擇這個方法。這個過程稱爲重載解析。至此,編譯器已獲得需要調用的方法名字和參數類型

(3)如果是private方法、static方法、final方法或者構造器,那麼編譯器將可以準確地知道要調用哪個方法。這種調用方式稱爲“靜態綁定‘,與此對應的是,調用的方法依賴於隱式參數的實際類型,並且在運行時實現動態綁定。

(4)當程序運行,並且採用動態綁定時,虛擬機一定調用那個最合適的方法。假設X的實際類型爲D,它是C的子類,如果D類存在方法f,就直接調用它;否則將在D類的超類尋找f。

每次調用方法都要進行搜索,時間開銷很大,因此虛擬機爲每個類創建了方法表,在實際調用的時候,虛擬機僅查找這個表就可以了



9 類的設計技巧

  • 保證數據私有
  • 要對數據進行初始化
  • 不要再類中過多的使用基本數據類型
  • 將職責過多的類進行分解
  • 類名和方法名要能夠體現他們的職責










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章