为什么我需要在这里明确编写构造函数?

时间:2013-11-08 14:12:57

标签: java

这就是我遇到问题的方法。我举个例子:

package check;

public class Check {
  int a,b;
  Check (int i,int j) {
    a = i;
    b = j;
  }
}

这很好。现在我想通过扩展Check来创建一个子类。所以我写道:

class V extends Check {

}

我写完后,一个十字架出现在Eclipse中,点击它我发现了一条消息:

implicit super constructor Check() is undefined for default constructor. Must define an explicit constructor.

我用Google搜索了问题并添加了

V (int i, int j) {
  super(i, j);
}
Eclipse也提出了这个建议。现在我有两个问题。

  1. 为什么class V完全使用构造函数是强制性的? AFAIK,创建构造函数不是必需的,因为JAVA编译器会自动创建默认构造函数以继续其操作。同样来自消息,它似乎也需要一个默认的构造函数,但不是我写的,但正如我所说,JAVA不是自动创建的吗?
  2. 另一件事,我将子类中的代码更改为V(int i, int j){ super.a=i; super.b=j}。但我仍然遇到错误。这是为什么?这段代码super.a=i; super.b=jsuper(i,j)不一样吗?另外,在V类中,我可能不需要使用b,那么为什么我需要用构造函数对它进行初始化呢?

7 个答案:

答案 0 :(得分:6)

  

1)为什么必须在V类中使用构造函数?   AFAIK,创建构造函数不是JAVA编译器所必需的   自动创建默认构造函数以进行其操作。   同样从消息中,它似乎也需要一个默认的构造函数,   但不是我写的,但正如我所说,JAVA并没有创造它   自动?

默认构造函数仅在没有其他构造函数存在时创建,当您创建构造函数Check(int i,int j)时,删除了默认构造函数。

如果在构造函数中没有包含对super的调用,则java会尝试默认调用super()。但是,由于父类中没有默认构造函数,因此无法执行此操作。

这种行为很好,因为您可能不需要默认构造函数;某些变量可以 初始化,以使对象正常运行。因此,需要有一种方法来删除默认构造函数,这是通过显式创建构造函数来完成的。

  

2)另一件事,我将子类中的代码更改为V(int i,int j){   super.a = I; super.b = j}。但我仍然得到错误。这是为什么?   这段代码不是super.a = i; super.b = j与super(i,j)相同?另外,在   第五类,我可能不需要使用b,那么我为什么需要   用构造函数初始化它?

代码

V(int i, int j){ 
   super.a=i; super.b=j
}

仍然没有调用父构造函数,因此变为

V(int i, int j){ 
   super();
   super.a=i; super.b=j
}

再次super()不存在

对super的一些调用必须存在以“设置”对象的父部分,一直到Object(所有对象隐含地扩展)。因此,您不能仅仅因为在子构造函数

中执行等效操作而省略父构造函数

答案 1 :(得分:4)

1)只有在您自己没有定义任何构造函数的情况下,编译器才会生成一个无参数构造函数。在类Check中,您已经定义了一个构造函数。

2)如果没有在您定义的构造函数中显式调用超类构造函数,编译器将生成对无参数构造函数的调用。由于类Check没有no-arg构造函数,编译器无法生成调用,您必须自己编写。

您可能想知道为什么类的构造函数必须调用其父类的构造函数。这是为了确保在您尝试使用它之前完全初始化对象:父构造函数可以初始化对象的某些方面,只能访问它自己,并在创建对象时调用构造函数是确保正确初始化的唯一方法。

答案 2 :(得分:1)

因为在Java中创建对象时,必须首先调用类超构造函数。由于您没有超级构造函数的默认值,并且您没有超类的默认构造函数,因此您需要为子类提供一个,调用super(i, j)

答案 3 :(得分:0)

创建类时,如果它没有构造函数,那么Java将为您提供默认构造函数。但是,如果您有一个或多个构造函数,那么Java不提供此默认(或零参数)构造函数。

在您的子类中,您还没有创建任何构造函数,因此java为您提供了一个默认构造函数。在子类中,构造函数中有一个对super()的隐式调用。由于尚未在超类中定义无参数构造函数,因此Java有效地尝试调用尚不存在的构造函数。

答案 4 :(得分:0)

认为它没有警告你,你写了一段代码,如:

V v = new V();

然后,您希望编译器的行为是什么?我的意思是,没有定义no-arg consructor。你需要明确地添加它。

Check() {

}

答案 5 :(得分:0)

Why is it compulsory to use a constructor at all for class V?

这是因为在check类中你明确地使用了参数化构造函数,并且也是V类的超类,所以如果你没有提到参数化的构造函数,那么你需要显式地调用super(),如果你不是在check类中定义任何参数化构造函数然后编译器将调用默认的无参数构造函数,并在那里放置super(),它负责调用Object类构造函数。

答案 6 :(得分:0)

  

错误原因 -

     

子类构造函数调用父类的构造函数   没有参数。

     

Check类中没有构造函数没有   参数。

此外,

Java编译器自动将super()构造函数插入到子类中。这个超级构造函数的含义是去并执行父类中不带参数的构造函数

根据你的计划:

Check (int i,int j) {
    a = i;
    b = j;
}

运行程序时,编译器会删除默认构造函数,因为父类中的构造函数需要两个参数。

如果没有为V类添加构造函数,Java编译器会自动插入默认构造函数。正如我之前所说的,当你在默认构造函数中extends另一个类(Check)时,Java编译器会自动在默认构造函数的第一行中插入super()

它看起来像这样:

class V extends Check {
   V(){super();}
}

我们可以将super()添加到子类的构造函数中,使其与父类中的现有构造函数匹配。

在您的第二个问题中,super()也会自动插入。在父类中没有匹配的构造函数,因为编译错误将会发生。

注意:添加super()时必须是子类构造函数中的第一行。