package com.wtd; public abstract class Car { private String name= "car"; public Car(String name) { this.name = name; } } public class JeepCar extends Car { public JeepCar(String name){ super(name); } }
現在我要創建JeepCar的實例,JeepCar jC= new JeepCar();那么我在debug的過程中,看到jvm運行的時候,先調用抽象父類的構造器Car(){},將屬性初始化,然后回到JeepCar(){}子類構造器。
疑問:因為知道抽象類是不能初始化的,那么super(name)調用父類構造器,會初始化父類實例嗎?如果不初始化父類實例,那么也就是說調用構造器並不一定初始化實例了,那這里的super(name)又有什么用處呢?
對這些疑問,自己很迷惑,所以只有求助於網絡了。從網上找了些感覺比較靠譜的解釋。
解釋1:
調用子類構造方法都會調用它的直接父類的構造方法。可以認為new才會返回一個實例的引用,而抽象類是不能new的(這個是規定,沒理由)。
調用子類構造方法是調用了它的抽象父類的構造方法,但構造方法是用來做初始化工作的,它並不會返回實例。
解釋2:
抽象類中的構造方法其實是用來給繼承的子類來用的,因為構造方法相當於初始化方法,當子類調用構造方法時必須調用父類構造方法,所以你可以在子類產生對象 時抽象類中按需求初始化抽象類中的字段以及執行一些初始化代碼。其實並不是一定要生成某個類的實例才調用構造方法,子類也需要調用父類構造方法。而生成實 例也並不一定會調用構造方法,在某些特殊實現中或者特殊情況下,生成實例不會調用構造方法。而調用了構造方法也不一定就生成了一個實例,但是那一定是一個 實例調用的,就像一個普通的實例方法一樣。
解釋3:
抽象類不能被實例化是說Person p=new Person();這樣是錯誤的;但是Person p=new Employee(); 是可以的,創建子類的實例,父類的引用指向它
在上述主程序中,new Employee后,它會初始化對象,初始化順序為:
父類靜態塊初始化---->子類靜態塊初始化---->父類非靜態塊初始化---->父類構造方法---->子類非靜態塊初始化---->子類構造方法。(先靜后動,先父后子)
這個主程序會先初始化person類的非靜態屬性和構造函數再初始化employees類的非靜態屬性和構造函數
這就是你第一個問題的當子類的父類為抽象類時,構造方法如何追溯?而抽象類作為父類也會創建實例么?沒有創建實例只是構造函數在對抽象類Person的屬性初始化,對於一個類的聲明,賦值 和使用兩件事情,前者不需要實例化,后者必須實例化 。
自己的簡單總結:類的構造器,不論抽象還是非抽象,作用都一樣,就是初始化屬性的;
只有構造器和new連在一塊使用時,才是創建類的實例(對象)。
抽象類中的構造方法是怎么回事?就是初始化屬性的作用。