final:
1.理解:凡是final修飾的東西都具有了不變的特性;
2.修飾對象:
1)final+類--->類無法被繼承;
2)final+方法--->方法無法被覆蓋;
3)final+變量--->只能被賦值一次;
eg:被 final 修飾的引用,由於只能被賦值一次,所以其儲存的地址不變,所以它的指向也就不會改變,但不代表其指向的對象內部的數據不會改變;
注意:
被 final 修飾的變量為實例變量時,必須手動初始化(否則報錯),不能系統自動賦值了;
final 修飾的靜態變量一般與static聯合使用,稱為常量,eg:public static final double PI = 3.1415926 ;
抽象方法:
1.概念:被 abstract 修飾的方法,無方法體( { } 也不能寫 ),而且不以 ” } “結尾,以 ” ;“ 結尾;
2.格式:public abstract void fangFa ( ) ;
3.注意:抽象方法可以有參數列表;
抽象方法被重寫時,abstract 要去掉;參數列表不能改變;並且加上方法體;
抽象類與接口:
1.抽象類:
1)概念:將類之間的共同特征提取出來,抽象為一個類,這種類就叫抽象類;
2)格式:abstract + class + 類名
3)抽象類可以被繼承,子類可以為抽象類,也可以不是,但如果不是抽象類,必須對抽象類(父類)中的所有抽象方法進行覆蓋;
4)注意:抽象類無法實例化為對象;
若抽象之間有共同特征,也可將其進一步抽象為一個抽象類;
final 與 abstract 不能聯合修飾一個東西;
抽象類中也有構造方法,意義:給子類使用;
抽象類中可以有普通方法,也可以有抽象方法,但是抽象方法必須出現在抽象類中,不能出現在非抽象類中;
2.接口:
1)定義: interface + 接口名
2)特性:
接口支持多繼承;
接口中所有的方法都是默認被 public abstract 修飾的,且可以省略,eg: 返回值類型 + 方法名(參數列表);
接口中的所有量都是默認被 public static final 修飾的,且可以省略,所以接口中只有常量,沒有變量;
接口被繼承不用 extends 用 implements(實現);
接口的完全抽象的性質,可以進一步使程序的耦合性降低,拓展性提高;
3)注意;
extends 可以與 implements 共存,extends 在前,implements 在后;
接口由於是完全抽象的,所以被實現時,也與抽象類遵循相同的規則,若子類不為抽象類,則需要對接口中的所有抽象方法都進行方法覆蓋
分析原因:因為繼承與實現都相當於將類體中或接口內的代碼復制粘貼到子類中,所以遵循” 抽象方法只能出現在 抽象類 / 接口中 “的原則,必須要對 抽象/接口 中的所有抽象方法進行方法覆蓋-->即將抽象方法轉化為普通方法 ;
3.抽象類與接口的區別;
1)構造方法:前有,后無;
2)繼承機制:前單繼承,后多繼承(interfaces 后可以加多個接口,extends 后只可以加一個類)
3)抽象類中的方法與量都無限制,接口中的方法只能是抽象方法,量只能是常量;
解析繼承,關聯,與實現:
1.繼承:” is a “, 例如:猴子是一種動物,則 猴子 extends 動物;
---使猴子繼承動物該有的特性
2.關聯:” has b “,例如:我有一雙鞋類,則 class 我 { 鞋 鞋 ; }
---將鞋類作為一種屬性寫在 我類 中,因為我穿鞋呀,所以利用關聯來使” 我 擁有了 鞋“
3.實現:” like c “,例如:廚師像一個菜單一樣,則 class 廚師 interfaces 菜單 { 重寫菜單中的方法 }
---對於” 顧客利用菜單來點菜 “的機制來說,廚師類來實現接口,顧客來調用接口
輔助理解代碼:
public class 顧客點西式柿子炒雞蛋 {
public static void main(String[] args) {
//利用多態機制創建美國廚師對象
FoodMenu cooker=new AmericanCooker();
//調用構造方法使 顧客拿到了菜單,並將對象美國廚師傳到了菜單中
Customer customer=new Customer(cooker);
//調用顧客中的點菜方法(顧客中的點菜方法調用菜單中的柿子炒雞蛋方法,此時菜單中的方法已被美國廚師中的方法覆蓋了,所以顧客吃到的是西式柿子炒雞蛋)
customer.order();
}
}
interface FoodMenu{
void shiZiChaoJiDan();
}
class ChinaCooker implements FoodMenu{
public void shiZiChaoJiDan(){
System.out.println("中國師傅做的柿子炒雞蛋!");
}
}
class AmericanCooker implements FoodMenu{
public void shiZiChaoJiDan(){
System.out.println("美國師傅做的柿子炒雞蛋!");
}
}
class Customer{
private FoodMenu foodMenu;
public Customer() {
}
public Customer(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
public FoodMenu getFoodMenu() {
return foodMenu;
}
public void setFoodMenu(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
public void order(){
foodMenu.shiZiChaoJiDan();
}
}
運行結果:
美國師傅做的柿子炒雞蛋!
Process finished with exit code 0
代碼解析;
1.菜單是一個接口(菜單上有一個抽象的照片:柿子炒雞蛋);
2.顧客面向菜單點菜,調用接口;
3.后台的廚師負責把柿子炒雞蛋做好,是接口的是實現者;
4.接口作用:這個飯館的菜單,讓顧客和后廚解耦合了,顧客不用找后廚,后廚不用找顧客,他們之間完全依靠這個抽象的菜單溝通;
5.總結:面向接口編程,可以降低程序的耦合度,提高程序的拓展力;接口的使用離不開多態機制(接口+多態才可以達到降低耦合度);任何一個接口都有調用者和實現者,接口可以將調用者與實現者解耦合,調用者面向接口調用,實現者面向接口編寫實現;
隨筆:
Java語言中凡是沒有方法體的方法都是抽象方法?
錯,Object 類中就有很多方法都沒有方法體,都是以 ” ;“ 結尾的,但他們 都不是抽象方法,eg:public native int hashCode( ) ;
此方法底層是調用了C++寫的動態鏈接庫程序,native 表示調用 JVM 本地程序;
由於博主目前只是一只猿寶寶,所以有些地方可能說的有些片面,若前輩們能夠指點一二就更好了 (~ ̄(OO) ̄)ブ