1. 程式人生 > >【收藏篇】Java基礎知識總結系列三

【收藏篇】Java基礎知識總結系列三

抽象類與介面:

抽象類:一般用於描述一個體系單元,將一組共性內容進行抽取,特點:可以在類中定義抽象內容讓子類實現,可以定義非抽象內容讓子類直接使用。它裡面定義的都是一些體系中的基本內容。

介面:一般用於定義物件的擴充套件功能,是在繼承之外還需這個物件具備的一些功能。

抽象類和介面的共性:都是不斷向上抽取的結果。

抽象類和介面的區別:

1:抽象類只能被繼承,而且只能單繼承。

介面需要被實現,而且可以多實現。

2:抽象類中可以定義非抽象方法,子類可以直接繼承使用。

介面中都是抽象方法,需要子類去實現。

3:抽象類使用的是 is a 關係。

介面使用的 like a 關係。

4:抽象類的成員修飾符可以自定義。

介面中的成員修飾符是固定的。全都是public的。

多 態★★★★★ 多 態★★★★★(面向物件特徵之一):函式本身就具備多型性,某一種事物有不同的具體的體現。

體現:父類引用或者介面的引用指向了自己的子類物件。//Animal a = new Cat();父類可以呼叫子類中覆寫過的(父類中有的方法)

多型的好處:提高了程式的擴充套件性。繼承的父類或介面一般是類庫中的東西,(如果要修改某個方法的具體實現方式)只有通過子類去覆寫要改變的某一個方法,這樣在通過將父類的應用指向子類的例項去呼叫覆寫過的方法就行了!

多型的弊端:當父類引用指向子類物件時,雖然提高了擴充套件性,但是隻能訪問父類中具備的方法,不可以訪問子類中特有的方法。(前期不能使用後期產生的功能,即訪問的侷限性)

多型的前提:

1:必須要有關係,比如繼承、或者實現。

2:通常會有覆蓋操作。

如果想用子類物件的特有方法,如何判斷物件是哪個具體的子類型別呢?

可以可以通過一個關鍵字 instanceof ;//判斷物件是否實現了指定的介面或繼承了指定的類

格式:<物件 instanceof 型別> ,判斷一個物件是否所屬於指定的型別。

Student instanceof Person = true;//student繼承了person類

————————————————————————————-java.lang.Object

Object:所有類的直接或者間接父類,Java認為所有的物件都具備一些基本的共性內容,這些內容可以不斷的向上抽取,最終就抽取到了一個最頂層的類中的,該類中定義的就是所有物件都具備的功能。

具體方法:

boolean equals(Object obj):用於比較兩個物件是否相等,其實內部比較的就是兩個物件地址。

2,String toString():將物件變成字串;預設返回的格式:類名@雜湊值 = getClass().getName() + ‘@’ + Integer.toHexString(hashCode())

為了物件對應的字串內容有意義,可以通過複寫,建立該類物件自己特有的字串表現形式。

public String toString(){

    return "person : "+age;

}

3,Class getClass():獲取任意物件執行時的所屬位元組碼檔案物件。

4,int hashCode():返回該物件的雜湊碼值。支援此方法是為了提高雜湊表的效能。將該物件的內部地址轉換成一個整數來實現的。

通常equals,toString,hashCode,在應用中都會被複寫,建立具體物件的特有的內容。

內部類:如果A類需要直接訪問B類中的成員,而B類又需要建立A類的物件。這時,為了方便設計和訪問,直接將A類定義在B類中。就可以了。A類就稱為內部類。內部類可以直接訪問外部類中的成員。而外部類想要訪問內部類,必須要建立內部類的物件。

class Outer{

int num = 4;    

class Inner {

    void show(){

        System.out.println("inner show run "+num);

    }

}

public void method(){

    Inner in = new Inner();//建立內部類的物件。

    in.show();//呼叫內部類的方法。 //內部類直接訪問外部類成員,用自己的例項物件;

}                                        //外部類訪問內部類要定義內部類的物件;

}

當內部類定義在外部類中的成員位置上,可以使用一些成員修飾符修飾 private、static。

1:預設修飾符。

直接訪問內部類格式:外部類名.內部類名 變數名 = 外部類物件.內部類物件;

Outer.Inner in = new Outer.new Inner();//這種形式很少用。

但是這種應用不多見,因為內部類之所以定義在內部就是為了封裝。想要獲取內部類物件通常都通過外部類的方法來獲取。這樣可以對內部類物件進行控制。

2:私有修飾符。

通常內部類被封裝,都會被私有化,因為封裝性不讓其他程式直接訪問。

3:靜態修飾符。

如果內部類被靜態修飾,相當於外部類,會出現訪問侷限性,只能訪問外部類中的靜態成員。

注意;如果內部類中定義了靜態成員,那麼該內部類必須是靜態的。

內部類編譯後的檔名為:”外部類名$內部類名.java”;

為什麼內部類可以直接訪問外部類中的成員呢?

那是因為內部中都持有一個外部類的引用。這個是引用是 外部類名.this

內部類可以定義在外部類中的成員位置上,也可以定義在外部類中的區域性位置上。

當內部類被定義在區域性位置上,只能訪問區域性中被final修飾的區域性變數。

匿名內部類(物件):沒有名字的內部類。就是內部類的簡化形式。一般只用一次就可以用這種形式。匿名內部類其實就是一個匿名子類物件。想要定義匿名內部類:需要前提,內部類必須繼承一個類或者實現介面。

匿名內部類的格式:new 父類名&介面名(){ 定義子類成員或者覆蓋父類方法 }.方法。

匿名內部類的使用場景:

當函式的引數是介面型別引用時,如果介面中的方法不超過3個。可以通過匿名內部類來完成引數的傳遞。

其實就是在建立匿名內部類時,該類中的封裝的方法不要過多,最好兩個或者兩個以內。

//面試

    //1

    new Object(){

        void show(){

            System.out.println("show run");                

        }

    }.show();                                    //寫法和編譯都沒問題

    //2

    Object obj = new Object(){

        void show(){

            System.out.println("show run");

        }

    };

    obj.show();                                //寫法正確,編譯會報錯

    1和2的寫法正確嗎?有區別嗎?說出原因。

    寫法是正確,1和2都是在通過匿名內部類建立一個Object類的子類物件。

    區別:

    第一個可是編譯通過,並執行。

    第二個編譯失敗,因為匿名內部類是一個子類物件,當用Object的obj引用指向時,就被提升為了Object型別,而編譯時會檢查Object類中是否有show方法,此時編譯失敗。

異 常:★★★★ –java.lang.Throwable:

Throwable:可丟擲的。

|--Error:錯誤,一般情況下,不編寫針對性的程式碼進行處理,通常是jvm發生的,需要對程式進行修正。

|--Exception:異常,可以有針對性的處理方式

這個體系中的所有類和物件都具備一個獨有的特點;就是可拋性。

可拋性的體現:就是這個體系中的類和物件都可以被throws和throw兩個關鍵字所操作。

throw與throws區別:

throws是用來宣告一個方法可能丟擲的所有異常資訊,而throw則是指丟擲的一個具體的異常型別。此外throws是將異常宣告但是不處理,而是將異常往上傳,誰呼叫我就交給誰處理。

throw用於丟擲異常物件,後面跟的是異常物件;throw用在函式內。

throws用於丟擲異常類,後面跟的異常類名,可以跟多個,用逗號隔開。throws用在函式上。

throws格式:方法名(引數)throws 異常類1,異常類2,…..

throw:就是自己進行異常處理,處理的時候有兩種方式,要麼自己捕獲異常(也就是try catch進行捕捉),要麼宣告丟擲一個異常(就是throws 異常~~)。

處理方式有兩種:1、捕捉;2、丟擲。

對於捕捉:java有針對性的語句塊進行處理。

try {

需要被檢測的程式碼;

}

catch(異常類 變數名){

異常處理程式碼;

}

fianlly{

一定會執行的程式碼;

}

定義異常處理時,什麼時候定義try,什麼時候定義throws呢?

功能內部如果出現異常,如果內部可以處理,就用try;

如果功能內部處理不了,就必須宣告出來,讓呼叫者處理。使用throws丟擲,交給呼叫者處理。誰呼叫了這個功能誰就是呼叫者;

自定義異常的步驟:

1:定義一個子類繼承Exception或RuntimeException,讓該類具備可拋性(既可以使用throw和throws去呼叫此類)。

2:通過throw 或者throws進行操作。

異常的轉換思想:當出現的異常是呼叫者處理不了的,就需要將此異常轉換為一個呼叫者可以處理的異常丟擲。

try catch finally的幾種結合方式:

1,

try

catch

finally

這種情況,如果出現異常,並不處理,但是資源一定關閉,所以try finally集合只為關閉資源。

記住:finally很有用,主要使用者關閉資源。無論是否發生異常,資源都必須進行關閉。

System.exit(0); //退出jvm,只有這種情況finally不執行。

注意:

如果父類或者介面中的方法沒有丟擲過異常,那麼子類是不可以丟擲異常的,如果子類的覆蓋的方法中出現了異常,只能try不能throws。

如果這個異常子類無法處理,已經影響了子類方法的具體運算,這時可以在子類方法中,通過throw丟擲RuntimeException異常或者其子類,這樣,子類的方法上是不需要throws宣告的。

多執行緒:★★★★ 返回當前執行緒的名稱:Thread.currentThread().getName()

執行緒的名稱是由:Thread-編號定義的。編號從0開始。

執行緒要執行的程式碼都統一存放在了run方法中。

執行緒要執行必須要通過類中指定的方法開啟。start方法。(啟動後,就多了一條執行路徑)

start方法:1)、啟動了執行緒;2)、讓jvm呼叫了run方法。

Thread類中run()和start()方法的區別:

start():用start方法來啟動執行緒,真正實現了多執行緒執行,這時無需等待run方法體程式碼執行完畢而直接繼續執行下面的程式碼。通過呼叫Thread類的start()方法來啟動一個執行緒,這時此執行緒處於就緒(可執行)狀態,並沒有執行,一旦得到cpu時間片,就開始執行run()方法,這裡方法run()稱為執行緒體,它包含了要執行的這個執行緒的內容,Run方法執行結束,此執行緒隨即終止。

run():run()方法只是類的一個普通方法而已,如果直接呼叫Run方法,程式中依然只有主執行緒這一個執行緒,其程式執行路徑還是隻有一條,還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下面的程式碼,這樣就沒有達到寫執行緒的目的。

總結:start()方法最本質的功能是從CPU中申請另一個執行緒空間來執行 run()方法中的程式碼,它和當前的執行緒是兩條線,在相對獨立的執行緒空間執行,也就是說,如果你直接呼叫執行緒物件的run()方法,當然也會執行,但那是 在當前執行緒中執行,run()方法執行完成後繼續執行下面的程式碼.而呼叫start()方法後,run()方法的程式碼會和當前執行緒併發(單CPU)或並行 (多CPU)執行。所以請記住一句話:呼叫執行緒物件的run方法不會產生一個新的執行緒,雖然可以達到相同的執行結果,但執行過程和執行效率不同

建立執行緒的第一種方式:繼承Thread ,由子類複寫run方法。

步驟:

1,定義類繼承Thread類;

2,目的是複寫run方法,將要讓執行緒執行的程式碼都儲存到run方法中;

3,通過建立Thread類的子類物件,建立執行緒物件;

4,呼叫執行緒的start方法,開啟執行緒,並執行run方法。

執行緒狀態:

被建立:start()

執行:具備執行資格,同時具備執行權;

凍結:sleep(time),wait()—notify()喚醒;執行緒釋放了執行權,同時釋放執行資格;

臨時阻塞狀態:執行緒具備cpu的執行資格,沒有cpu的執行權;

消亡:stop()

最後,你跟我一樣如果喜歡java,也在學習java的道路上奔跑,歡迎你加入java學習群:527999065 群內每天都會分享java最新業內資料,共同交流學習,讓學習變(編)成(程)一種習慣!