java-day23
靜態導入
在JDK5.0的時候,引入的一個新的語法
在當前類中,可以使用import語法,把類中的靜態屬性或者方法直接導入進來,這樣在類中可以直接訪問中國靜態屬性或方法,連類名都不用,相當於使用自己類中的靜態屬性或方法一樣。
final修飾符
final本身的含義是最終的,使用這個修飾符可以修飾類、方法、屬性、局部變量
-
使用final修飾類
-
如果一個類被final修飾了,那麼這個類就不能被子類繼承了。
-
public final class Person{} public class Student extends Person{}
-
String類是final的不能進行拓展
-
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xTiu0OPF-1584676282880)(3-20.assets/1584671607265.png)]
-
-
使用final修飾方法
-
public class Person{ public final void run(){ System.out.print("run方法很重要,不能被改寫"); } } public class Student extends Person{ public void run(){ System.out.print("Student running"); } }
-
思考,Object類中有一個方法toString, 這個方法可以返回個對象的字符串形式,還有一個方法getClass, 這個方法可以返回對象在運行時的實際類型,子類繼承了Object,如果想改變這兩個方法的默認執行代碼,是否可以在子類進行重寫?
- toString方法可以重寫
- public String toString()
- getClass方法不能重寫
- public final Class getClass()
- toString方法可以重寫
-
-
final修飾變量
-
使用final修飾的變量,就變成了一個常量,可以賦值一次,之後這個值就不允許再改變。
-
修飾局部變量
-
注意:局部變量不能使用static
-
使用final修飾的變量,就變成了一個常量,可以賦值一次,之後這個值就不允許再改變
-
public void print(final int a){ //編譯報錯 //這個方法的參數,將來再調用方法的時候,進行傳參賦值, //一旦賦值完成,在方法中就不能對a值進行改變了 a = 1; } public void test(){ final int b; b = 1; //編譯報錯 b = 2; }
-
-
修飾類中的非靜態屬性
-
public class Person{ private final int a; } //編譯報錯 //a是final修飾的 //只能由程序員賦值,並且只能賦值一次
-
什麼地方可以給這個final變量賦值?
-
聲明同時賦值
-
public class Person{ private final int a = 1; }
-
匿名代碼塊中賦值
-
public class Person{ private final int a; { a = 1; } }
-
在構造器中賦值
-
public class Person{ private final int a; public Person(){ this.a = 1; } } /* 如果在構造器給final修飾的非靜態屬性賦值, 同時類中有定義了多個構造器,那麼就要給類中 所有構造器裏面對final修飾的變量賦值,保證 使用任何一個構造器創造claim的對象都已經完 成了對final屬性的賦值。 */ public class Person{ private final int a; public Person(){ this.a = 1; } public Person(String name){ //編譯報錯 //沒有給a賦值 } }
-
-
-
修飾類中的靜態屬性
-
聲明同時賦值
-
public class Person{ private static final int a = 1; }
-
靜態代碼塊中賦值
-
public class Person{ private final int a; static{ a = 1; } }
-
注意:在類中使用final修飾的屬性,就變成了類中的常量,這個值確定後就不會再改變了,對於這種變量的名字,一般都是以字母全大寫來表示,如果多個字母用下劃線進行連接。
-
-
修飾引用類型的變量
-
修飾基本類型的特點:
- final int a =1;
- 一旦確定就不能再進行改變。
-
修飾引用類型的特點:
-
final Person p = new Person();
-
這個變量p就成了常量,p保存的是內存地址值,地址值一旦確定,就無法改變,這個p只能指向當前對象。
-
p保存的內存地址無法改變,但是我們可以使用變量p去訪問對象中的屬性和方法,也可以修改這個對象中的屬性值,如果這個屬性不是final修飾的話。
-
//編譯報錯 final Person p = new Person(); p = new Person(); //編譯通過 //改變的是對象的屬性值 //前提是屬性沒有被final定義 final Person p = new Person(); p.name = "Tom"; p.name = "Jack";
-
-
-
-
abstract修飾符
-
abstract可以用來修飾類、方法,如果修飾類,那麼這個類就是抽象類,如果修飾方法,那麼這個方法就是抽象方法。
-
抽象方法
-
只有方法的聲明,沒有方法的實現,這樣的方法就是抽象方法。
-
//一個有聲明沒有實現的方法 public void test(); //這樣的方法需要使用abstract修飾符來修飾,說明他是一個抽象方法 public abstract void test(); //既有方法的聲明又有方法的實現 public void test(){ System.out.println("hello"); } //既有方法的聲明又有方法的實現(空實現) public void test(){ }
-
-
抽象類
-
只要使用abstract修飾的類就是一個抽象類
-
//普通的類 public class Person{} //抽象類 public abstract class Person{}
-
抽象類和抽象方法之間的關係
- 抽象類中可以有抽象方法,也可以沒有
- 一個類有抽象方法一定是抽象類
-
抽象類和抽象方法的特點
- 抽象方法因爲沒有實現,所以是沒有辦法執行的,只有等這個方法實現以後,才能調用執行這個方法的實現代碼。
- 不能執行是因爲沒有實現的代碼,但是可以進行調用,因爲一個引用調用方法,最後會調用執行哪個對象中的方法要看運行時這個引用所指向的對象是誰,以及對象中是否重寫過這個方法。
- 調用:編譯時
- 執行:運行時
- 抽象類因爲代碼塊中可能會存在沒有實現的抽象方法,所以我們不能使用這個抽象類直接new對象的,假設抽象類中有抽象方法,我們new出了這個抽象類的對象,那麼用這個對象調用中的類中抽象方法沒有意義,不合語法要求。所以語法層面上不允許我們創建。
-
抽象類和它的子類
- 抽象類不能使用new創建對象,但是抽象類可以被子類繼承。將來可以使用子類創建對象,再結合java中的多態,再使用父類的引用,指向子類對象,這時候父類就是這裏說的抽象類了。
- 子類中繼承了父類,父類是一個抽象類,那麼子類就必須把父類中的抽象方法給實現了,這裏說的實現,語法上就是我們之前用的重寫,但是從意義上講,用實現這個詞來描繪會更合適一些。
- 如果子類沒有實現父類中的抽象方法,或者沒全部把父類中的抽象方法給全部實現,那麼這個子類也必須要聲明爲抽象類。因爲抽象方法是可以被繼承的,所以父類中假設有5個抽象方法,子類繼承後,就相當於子類中有這5個抽象方法。
-
-
final修飾的方法不可以聲明爲抽象的
- 只要是不能重寫的方法都不能聲明爲抽象方法,將來沒有辦法實現。
- 注意,抽象方法,就是爲了將來讓子類中去重寫實現的。抽象方法可以調用,但不能執行,調用之後將來執行的一定是這個抽象方法實現。 (需要用到多態和重寫)
-
靜態方法可以使用final修飾
-
//編譯通過 //fina1和static的含義之間沒有衝突 public static final void say(){}
-
-
抽象類中是否有構造器?
- 可以有構造器。普通類中能寫什麼屬性、方法、構造器、代碼塊,那麼抽象方法中就可以寫什麼屬性、方法、構造器、代碼塊。
- 抽象類中的構造器雖然不能直接使用它創建對象,但是可以在創建子類對象的時候【super()】,子類的構造器中會調用這個父類中的構造器。
-
爲什麼要編寫抽象方法?
- 在一個類中實現方法時候,會遇到一些問題,通過思考分析後會發現,這個方法我們在這裏是沒有辦法很合適的進行實現的,一般的原因會是當前這個類所表示的範圍比較大,它的下面很多子類的情況各自不同,所以導致我們沒辦法在這個範圍比較大的類中,很好的對這個方法進行實現,那麼我們就可以把這個方法聲明爲抽象方法,然後將來在子類中對象這個方法進行重寫實現,象這個方法進行重寫實現,因爲子類一般表 示的範圍比較小,情況比較具體,所以可以在子類中進行很好的實現。