在java中,面向對象毫無疑問是java的重中之重,今天我們來看一看java面向對象的三大特性之一繼承。
首先我們來了解一下類的結構是怎樣的?
類中主要有成員屬性,成員方法,靜態屬性,靜態方法,構造方法(暫不考慮代碼塊)。成員屬性和成員方法是屬於對象的,靜態屬性和靜態方法是屬於類的,如下圖所示。
類的結構我們知道了(為后面做鋪墊的),那么接下來就正式的進入了我們的主題,繼承!
1.什么是繼承?
(1)用來提高代碼的復用性
(2)將相同的功能模塊封裝到方法中需要使用時調用方法達到代碼復用的目的
(3)通過繼承將多個類中的相同的類容摘取出來,變成一個新類,讓其他類和當前的新類產生關系,達到代碼復用性的目的
2.怎么樣才能繼承?
使用關鍵字extends,如下所示,B繼承A, A是B的父類,B是A的子類。當一個類不顯示的繼承其它類時,默認繼承Object類,Object是所有的父類。在java中只有直接父類和間接父類關系,沒有兄弟關系,爺孫關系。
使用繼承以后就可以子類就是可以使用父類中的方法了,如下圖所示,子類的對象可以直接調用父類中方法,而不用重新定義方法。然而其實很多時候因為子類的需求和父類的需求是不同的,所以需要重寫父類的方法。這樣的話,代碼的復用率就低了。另外,java中是單繼承的,不允許出現多繼承,當一個類已經繼承了這個類就不會繼承其它類,代碼的可擴展性就大大的降低了,其次,一旦類的繼承鏈越來越長的,維護的成本就變的相當高了,當改動其中一個類時,很多類都需要進行改動,可能還不如重構來的快。大多時候我們都是面向接口編程的,這個話題我們有空可以再來聊一聊!
3,父類的東西,子類可以全部繼承嗎?
不,當然不是;
3.1權限修飾符的繼承問題
被private修飾的,是不可以被繼承的,因為private修飾的只能在本類中可見,子類是不可見的;另外父類被protected或public修飾的,子類是可以繼承的;被默認修飾符修飾的只能在同包下的子類是可以繼承的;
3.2 構造器的繼承問題
構造器是不會被子類繼承的,但子類的對象在初始化時會默認調用父類的無參構造器,當父類顯示寫了有參構造器,且沒有無參構造器。子類繼承父類的時候必須顯示的調用父類的有參構造器。調用的方式可以使用super(a,b)來調用;
3.3 static修飾符的繼承問題
子類是不會繼承父類被static修飾的方法和變量,但是可以調用;如圖所示,this.a()就會報錯,普通方法的繼承this.method_a()就不會報錯;
4,方法的重寫(覆蓋)
重寫是發生在方法層面上的,屬性是不會重寫的,可以被隱藏,隱藏是針對於靜態方法和靜態屬性的。另外重寫是針對於實例方法的,子類的實例方法不能覆蓋父類的靜態方法,子類的靜態方法不能隱藏父類的實例方法;當子類需要擴充父類的功能時,需要會對父類的方法進行重寫,那么重寫必須滿足哪些條件呢?,如下圖所示,
4.1,即要重寫的方法的方法名和參數列表必須相同,可以在要重寫的方法的上方添加@Override注解,來判斷是否正確的進行了重寫;
4.2 即子類的返回值類型和拋出的異常類型必須要小於等於父類的類型
4.3 要重寫的方法的權限修飾符必須要大於等於父類方法的權限,不然就會報錯,
注意:重寫是對於實例方法而言的,隱藏是對於靜態方法和屬性而言的(主要是由父類和子類中相同的方法名和屬性名引起的),重寫是受RTTI(運行時檢查)約束的,即運行期間才知道該方法屬於哪個類的,隱藏是不受該約束的,即編譯期間就可以知道該方法和屬性屬性屬於哪個類的。
下面有一道網上的面試題,主要針對於重寫和隱藏的,小伙伴可以做做看!!!
package com.shsxt.test;
public class Test07 {
public static void main(String[] args) {
Circle circle=new Circle();
System.out.println(circle.name);
circle.printType();
circle.printName();
Shape shape = new Circle();
System.out.println(shape.name);
shape.printType();
shape.printName();
}
}
class Shape {
public String name = "shape";
public void printType() {
System.out.println("this is shape");
}
public static void printName() {
System.out.println("shape");
}
}
class Circle extends Shape {
public String name = "circle";
public void printType() {
System.out.println("this is circle");
}
public static void printName() {
System.out.println("circle");
}
}
答案: