爲什麼在父類中是必需的默認構造函數(明確的),如果它有一個argumented構造爲什麼默認構造函數在父類中是必需的,如果它具有參數構造函數?
class A {
A(int i){
}
}
class B extends A {
}
class Main {
public static void main(String a[]){
B b_obj = new B();
}
}
這將是一個錯誤。
爲什麼在父類中是必需的默認構造函數(明確的),如果它有一個argumented構造爲什麼默認構造函數在父類中是必需的,如果它具有參數構造函數?
class A {
A(int i){
}
}
class B extends A {
}
class Main {
public static void main(String a[]){
B b_obj = new B();
}
}
這將是一個錯誤。
(像邁克爾,我認爲你的意思是讓B
延長A
)。
有在工作兩個方面的位置:
如果做明確指定一個構造函數(如在A
)Java編譯器將而不是爲你創建一個無參數的構造函數。
如果不明確(如在B
)Java編譯器指定一個構造函數將創建一個這樣你參數的構造函數:
B()
{
super();
}
(可訪問性取決於無障礙這個類本身。)
這是試圖調用超類的無參數構造函數 - 所以它必須存在。你有兩個選擇:
A
B
其中明確調用基類的構造函數與適當的int
參數提供一個參數的構造函數。當然,如果像這樣寫它不是JAVA錯誤。
如果你會使用JAVA語法,它不會是一個錯誤。
如果在不同的文件/包中,A類和B類對彼此一無所知。
A類不需要默認的構造函數,只需要一個參數構造函數就可以正常工作。
如果B擴展A,您可以簡單地在B的構造函數中使用對super(int a)的調用,一切都很好。 對於沒有調用super(空或者不是)的構造函數來說,擴展一個超類,編譯器會向super()添加一個調用。
進一步的閱讀看看Using the Keyword super
真的很有價值的答案。但是爲什麼super()是由編譯器隱式添加的一個小澄清。 – bharanitharan
@ user358099我已經爲您編輯的問題添加了一個新答案。 – Farmor
假設你的意思是寫class B extends A
:
每一個構造函數調用父類的構造;如果它不隱含地調用無參數超類的構造函數。
如果(且只有)一個類聲明瞭沒有構造函數,Java編譯器纔會給它一個默認構造函數,它不接受任何參數並調用超類的無參數構造函數。在你的例子中,A
聲明瞭一個構造函數,因此沒有這樣的默認構造函數。類B
未聲明構造函數,但無法獲取默認構造函數,因爲其超類沒有無參數構造函數要調用。由於一個類必須總是有一個構造函數,所以這是一個編譯器錯誤。
它的一個編譯器錯誤我的疑問是...爲什麼父類顯式應該有一個默認的構造函數......雖然它有一個有爭議的構造函數 – bharanitharan
@ user358099:因爲隱式的默認構造函數只有在沒有隱式構造函數時纔會創建。這是因爲程序員可能不希望他的類具有無參數的構造函數,所以總是隱式地創建一個非常糟糕的語言設計。 –
說這個編譯,你期望它打印什麼?
class A{
A(int i){
System.out.println("A.i= "+i);
}
}
class B extends A {
public static void main(String... args) {
new B();
}
}
當A構造一個值i
將被傳遞,但是編譯器不知道它應該是什麼,所以你必須在構造函數(任何構造明確指定,它不必是一個默認的)
爲什麼需要默認構造函數(明確)在父類,如果它有一個argumented構造
我會說這種說法是不總是正確的。理想情況下,其不需要。
規則是:如果您明確提供了參數化構造函數,那麼默認構造函數(非參數化)對類不可用。
For Example :
class A {
A(int i){
}
}
class B extends A {
}
所以,當你寫
B obj_b = new B();
它實際上是調用Java提供到B的隱式構造,這再次調用超(),這應該是一個理想的()。但是既然你已經爲A提供了參數化的構造函數,那麼默認的構造函數i:e A()就不可用於B()。
這就是你需要爲B()專門聲明A()來調用super()的原因。
我猜它是因爲當你有一個空的參數列表超級變量不能實例化。對於空參數列表,我的意思是如果超類具有非參數構造函數,則編譯器可以添加隱式超級()。
例如,如果你鍵入:
int a;
System.out.print(a);
你會得到一個錯誤與我的想法是一樣的邏輯錯誤。
當我們有參數構造函數。我們通過設計明確地約束消費者。他無法創建沒有參數的類的對象。有時候我們需要強制用戶提供價值。對象應僅通過提供參數(默認值)來創建。
class Asset
{
private int id;
public Asset(int id)
{
this.id = id;
}
}
class Program
{
static void Main(string[] args)
{
/* Gives Error - User can not create object.
* Design bound
*/
Asset asset1 = new Asset();/* Error */
}
}
甚至子類無法創建。因此它是良好設計的行爲。
Why default constructor is required(explicitly) in a parent class if it
has an argumented constructor
不一定!
現在您的B級
class B extends A {
}
你沒有提供的B類任何構造這樣一個默認的構造函數將被放置
。現在每個構造函數都必須調用其中的一個超類構造函數。在你的情況下,類B中的默認構造函數將嘗試調用類A中的默認構造函數(它是父類),但是因爲在類A中沒有默認構造函數(因爲您已經在類A中明確提供了帶有參數的構造函數,所以在A類中沒有默認構造函數),您將會收到錯誤消息。
你可能做的是
要麼不提供任何參數的構造在A類
A()
{
//no arg default constructor in Class A
}
OR
明確寫入無參數的構造函數中的B和打電話給你超有一些默認的int參數。
B()
{
super(defaultIntValue);
}
底線是對於要創建的對象完全繼承層次結構中每個父的構造必須被調用。哪些人打電話真的是你的設計選擇。但是,如果你沒有明確提供任何java將默認構造函數super()調用作爲你的每個子類構造函數的第一行,現在如果你沒有超類中的那一行,那麼你會得到一個錯誤。
如果子類構造函數沒有顯式調用超類的其他構造函數,那麼每個子類的構造函數都會調用超類的默認構造函數。所以,如果你的子類構造函數明確地調用了你提供的超類構造函數(帶有參數),那麼在超類中不需要任何參數構造函數。 因此,下面將編譯:
class B extends A{
B(int m){
super(m);
}
}
但下面將無法編譯,除非你明確地提供超類無參數的構造函數:
class B extends A{
int i;
B(int m){
i=m;
}
}
有要注意的時候幾件事情使用構造函數以及如何在基類和超類中聲明它們。由於在超類或基類中可用或存在構造函數的可能性很多,這可能會讓人有些困惑。我會努力鑽研一切準備:
如果你明確任何class(基類/超類)定義構造函數,Java編譯器將無法在相應類別爲您創建的任何構造函數。
如果您沒有在任何類(基類/超類)中顯式定義構造函數,那麼Java編譯器將在該類中爲您創建一個無參數構造函數。
如果你的類是一個從超類繼承的基類,並且你沒有顯式地在該基類中定義構造函數,那麼不僅會爲你創建一個無參構造函數(就像上面那樣)編譯器,但它也會隱式地從超級類中調用無參數構造函數。
class A
{
A()
{
super();
}
}
如果super()被調用(由編譯器顯式或隱式調用),編譯器會期望你的超類有一個沒有參數的構造函數。如果它沒有在沒有參數的超類中找到任何構造函數,它會給你一個編譯錯誤。
如果調用超(參數)參數,編譯器會希望你的超類有一個帶參數(數量和參數類型應該匹配)的構造函數。如果它沒有在你的超類中找到這樣的構造函數,它會給你一個編譯錯誤。 (超(參數)永遠不能被編譯器隱式調用。它必須被明確地把你的代碼(如果需要)。)
我們可以從上面的規則總結了一些東西
另一件需要注意的事情是,如果你的超類有一個私有構造函數,那麼當你編譯你的子類時會產生一個錯誤。這是因爲如果你不在你的子類中編寫構造函數,它會調用超類的構造函數,而隱式的super()將嘗試在超類中尋找一個無參數的構造函數,但是不會找到它。
@ user358099:爲了清楚表明它試圖調用無參數superconstructor。 –