![](/img/trans.png)
[英]Why the default constructor is not provided when typing an argument-ed constructor in java?
[英]Why default constructor is required in a parent class if it has an argument-ed constructor?
如果父類具有帶參數的構造函數,為什么在父類中需要(顯式)默認構造函數
class A {
A(int i){
}
}
class B extends A {
}
class Main {
public static void main(String a[]){
B b_obj = new B();
}
}
這將是一個錯誤。
這里有兩個方面在起作用:
如果您確實明確指定了構造函數(如在A
),則 Java 編譯器不會為您創建無參數構造函數。
如果您沒有顯式指定構造函數(如在B
),Java 編譯器將為您創建一個無參數構造函數,如下所示:
B() { super(); }
(可訪問性取決於類本身的可訪問性。)
那是試圖調用超類無參數構造函數 - 所以它必須存在。 您有三個選擇:
A
顯式提供無參數構造函數B
中顯式提供無參數構造函數,該構造函數使用適當的int
參數顯式調用基類構造函數。B
提供一個參數化構造函數,它調用基類構造函數如果父類具有帶參數的構造函數,為什么在父類中需要(顯式)默認構造函數
我會說這種說法並不總是正確的。 理想情況下它不是必需的。
規則是:如果您顯式提供了帶參數的構造函數,則該類無法使用默認構造函數(無參數)。
For Example :
class A {
A(int i){
}
}
class B extends A {
}
所以當你寫
B obj_b = new B();
它實際上調用了java提供的隱式構造函數給B,B又調用了super(),理想情況下應該是A()。 但是由於您為 A 提供了帶參數的構造函數,因此默認構造函數 i:e A() 對 B() 不可用。
這就是您需要為 B() 專門聲明 A() 以調用 super() 的原因。
如果子類構造函數沒有顯式調用超類的其他構造函數,則每個子類構造函數都會調用超類的默認構造函數。 因此,如果您的子類構造函數顯式調用您提供的超類構造函數(帶參數),則超類中不需要無參數構造函數。 因此,將編譯以下內容:
class B extends A{
B(int m){
super(m);
}
}
但是以下不會編譯,除非您在超類中明確提供沒有 args 構造函數:
class B extends A{
int i;
B(int m){
i=m;
}
}
假設您打算編寫class B extends A
:
每個構造函數都必須調用超類構造函數; 如果不是,則隱式調用無參數超類構造函數。
如果(且僅當)一個類沒有聲明構造函數,Java 編譯器會給它一個默認構造函數,它不帶參數並調用超類的無參數構造函數。 在您的示例中, A
聲明了一個構造函數,因此沒有這樣的默認構造函數。 類B
沒有聲明構造函數,但無法獲得默認構造函數,因為它的超類沒有可調用的無參數構造函數。 由於類必須始終具有構造函數,因此這是編譯器錯誤。
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 類中不提供 args 構造函數。
A()
{
//no arg default constructor in Class A
}
要么
明確地在 B 中寫入 no args 構造函數,並使用一些默認的 int 參數調用您的 super。
B()
{
super(defaultIntValue);
}
底線是,要創建一個對象,必須調用繼承層次結構中每個父級的完全構造函數。 調用哪個實際上是您的設計選擇。 但是,如果您沒有明確提供任何 java 會將默認構造函數 super() 調用作為每個子類構造函數的第一行,現在如果您在超類中沒有它,那么您將收到錯誤。
使用構造函數時需要注意一些事項,以及如何在基類和超類中聲明它們。 這可能會變得有些混亂,因為超類或基類中構造函數的可用性或存在性可能有很多。 我將嘗試深入研究所有可能性:
如果您在任何類(基類/超類)中顯式定義構造函數,Java 編譯器將不會在相應的類中為您創建任何其他構造函數。
如果您沒有在任何類(基類/超類)中顯式定義構造函數,Java 編譯器將在相應的類中為您創建一個無參數的構造函數。
如果您的類是從超類繼承的基類,並且您沒有在該基類中顯式定義構造函數,則編譯器不僅會為您創建無參數構造函數(如上點),而且還會從超類隱式調用無參數構造函數。
class A { A() { super(); } }
如果 super() 被調用(由編譯器顯式或隱式調用),編譯器將期望您的超類具有不帶參數的構造函數。 如果它在你的超類中沒有找到任何沒有參數的構造函數,它會給你一個編譯器錯誤。
類似地,如果調用 super(parameters) ,編譯器將期望您的超類具有帶參數的構造函數(參數的數量和類型應匹配)。 如果它在你的超類中找不到這樣的構造函數,它會給你一個編譯器錯誤。 ( Super(parameters) 永遠不能被編譯器隱式調用。如果需要,它必須顯式地放入你的代碼中。)
我們可以從上面的規則中總結出一些東西
另一件要注意的事情是,如果您的超類有一個私有構造函數,那么在您編譯子類時會產生錯誤。 這是因為如果您不在子類中編寫構造函數,它將調用超類構造函數,而隱式 super() 將嘗試在超類中查找無參數構造函數但找不到。
說這個編譯,你希望它打印什么?
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
,必須傳遞一個值,但是編譯器不知道它應該是什么,因此您必須在構造函數中明確指定它(任何構造函數,它都不必是默認的)
當我們有參數構造函數時。 我們通過設計明確綁定到消費者。 他不能在沒有參數的情況下創建該類的對象。 有時我們需要強制用戶提供價值。 對象只能通過提供參數(默認值)來創建。
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 */
}
}
連子類都不能創建。 因此,這是良好設計的行為。
擴展類時,會自動添加默認的超類構造函數。
public class SuperClass {
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
//super(); <-- Java automatically adds the default super constructor
}
}
但是,如果您重載了超類構造函數,這將取代默認值,因此調用super()
將導致編譯錯誤,因為它不再可用。 然后,您必須顯式添加重載的構造函數或創建一個無參數的構造函數。 請參閱以下示例:
public class SuperClass {
public SuperClass(String s, int x) {
// some code
}
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
super("some string", 1);
}
}
要么...
public class SuperClass {
public SuperClass() {
// can be left empty.
}
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
//super(); <-- Java automatically adds the no-parameter super constructor
}
}
因為如果您想阻止創建沒有任何數據的對象,這是一種好方法。
當然,如果這樣寫它是一個錯誤,它不是JAVA。
如果您將使用 JAVA 語法,則不會出錯。
如果在單獨的文件/包中,A 類和 B 類對彼此一無所知。
A 類根本不需要默認構造函數,它只使用參數構造函數就可以正常工作。
如果 B 擴展了 A,您只需在 B 的構造函數中調用 super(int a) ,一切都很好。 對於不調用擴展超類的 super(空/或不)的構造函數,編譯器將添加對 super() 的調用。
如需進一步閱讀,請參閱使用關鍵字超級
我猜這是因為當您有一個空參數列表時,無法實例化超級變量。 對於空參數列表,我的意思是如果超類具有非參數構造函數,編譯器可以添加隱式 super() 。
例如,如果您鍵入:
int a;
System.out.print(a);
你會得到一個錯誤,我認為是相同的邏輯錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.