封裝,繼承,多態

面向對象三大基石:封裝,繼承,多態。面試會問到。

Overriding  覆蓋  只存在於父子類之間,一定。

什麼時候纔是覆蓋呢?

class Father{
   public void run(){
   }
}

class Son extends Father{
   public void run(int a){
   }
}

注意:這是方法的重載,不是覆蓋!只是這個重載發生在父子類之間。

覆蓋是,子類參數列表與返回值都與父類相同,並且子類在覆蓋父類方法時,不能給出更嚴格的訪問控制,並且子類方法例外的類型是等於父子方法拋出的異常類型,或者是其子類型。

The exceptions thrown by an overriding method must be equal to or a subset of the exceptions thrown by the overridden method.

注意構造方法根本不能繼承,所以不存在覆蓋的問題。

訪問控制

private 本類內部可見

default 同類同包

protected 同包+不同包子類

要構造一個對象,先構造父類對象,再構造子類對象

構造一個對象的執行過程。

1.遞歸的構造父類對象-----------〉也就是說父類本身也要走這樣的步驟。
2.順序調用成員屬性賦初值語句
3.調用本類構造方法

後來課程領悟,類加載與構造對象是兩回事,類加載過程,1.static靜態成員加載,2運行static一次,靜態代碼塊,3如果有靜態內部類,賦值,對靜態內部類的賦值是指編譯產生的Employee$SomeInner.class文件的讀取。

如果類有靜態變量或者靜態塊,而且用到時(static初始化只有在必要的時候纔會進行,那麼就會在第一步之前執行一遍,先靜態變量,然後靜態塊,以後再怎麼new都不會執行,回到創建父類開始。

======〉引用Think In Java

在這裏有必要總結一下對象的創建過程。請考慮一個名爲Dog的類:
(1) 類型爲Dog的一個對象首次創建時,或者Dog類的static方法/static字段首次訪問時,Java解釋器必須找到Dog.class(在事先設好的類路徑裏搜索)。
(2) 找到Dog.class後(它會創建一個Class對象,這將在後面學到),它的所有static初始化模塊都會運行。因此,static初始化僅發生一次——在Class對象首次載入的時候。
(3) 創建一個new Dog()時,Dog對象的構建進程首先會在內存堆(Heap)裏爲一個Dog對象分配足夠多的存儲空間。
(4) 這種存儲空間會清爲零,將Dog中的所有基本類型設爲它們的默認值(零用於數字,以及boolean和char的等價設定)。
(5) 進行字段定義時發生的所有初始化都會執行。
(6) 執行構建器。正如第6章將要講到的那樣,這實際可能要求進行相當多的操作,特別是在涉及繼承的時候。

=====================

多態-1.編譯時多態      方法重載
         2.運行時多態      一個對象可能會具有多個類型

對象是客觀的。

人類對對象的認識是主觀的

當人看到一個不能識別的,有生命的,區別人的東西時,會類來認識該事物。

也就是Animal a = new Dog();子類對象可以使用父類對象來引用。

Animal被稱爲編譯時類型,而a真正的對象類型是運行時類型。

3個原則:

1.對象不變(運行時類型不變)(客觀的肯定不會改變)
2.只能調用編譯時類型的方法,方法調用時,檢查編譯時類型內部是否定義了該方法。
   也就是說,在你以一個一個動物來看待一隻狗時,你是不會知道它有散步的方法的。
3.RTTI,運行時,動態類型判定(看運行時類型),子類覆蓋了(Overriding)父類方法,那麼調用運行時類型對象的方法。

a instanceof 類名(編譯時類型)
a爲對象變量
判斷a是否被聲明爲後面類的對象。
用在強制類型轉換之前。如果轉換錯了,java.lang.ClassCastException 運行時例外

記住,方法只有覆蓋時,調用尋找運行時類型。而Overloading ->編譯時多態->看編譯時類型。

屬性,重載阿,都要看編譯時類型。

package com.ljl;

public class TestClass {
    
public void print(B b){
        System.out.println(
"is B");        
    }

    
//    public void print(A a){
//        System.out.println("is A");
//    }
    
    
public static void main(String[] args)
    
{
        TestClass tc 
= new TestClass();
        A a 
= new B();
        tc.print(a);
    }

}


class A{}

class B extends A{}

爲什麼子類覆蓋父類方法時,訪問控制符只能更寬泛。因爲如果父類方法爲public,子類方法爲private,那麼多態時,察看父類方法可以調用(可調用編譯時類型所定義的方法),而動態類型判斷時,調用子類方法,發現爲private,完蛋了。
 

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