在Java中,构造函数可以有返回类型吗?

11
以下代码会导致编译错误:
class parent {
  parent(int a){}
}

class child extends parent{}

错误:

Main.java:6: cannot find symbol
symbol  : constructor parent()
location: class parent
class child extends parent{}
^
1 error

我试图做不同的事情,发现在父构造函数中添加返回类型就可以消除错误!!!

class parent {
  int parent(int a){}
}

class child extends parent{}

我读过构造函数不应该有返回类型,但显然并不总是正确的。那么我的问题是,在什么情况下我们应该为构造函数指定返回类型?


2
你漏掉了一个 public 访问修饰符,是吗? - In silico
4
可能更容易这样思考:如果一个函数有返回类型,那它不是构造函数,而是一个方法。 - Michael Borgwardt
7
将来不要说“编译错误”,而是说“具有消息'yabba dabba'的编译错误”。您不应忽略该消息,它说明了问题的原因。 - BalusC
2
其实,这个问题确实有一定的价值。我投票支持重新开放。抱歉之前太仓促了。 - polygenelubricants
1
你可以将构造函数看作具有当前类名的返回类型,但没有方法名,如果这样更容易理解的话。 - Powerlord
显示剩余2条评论
11个回答

29

情况1下,子类没有任何构造函数,因此编译器会为您添加一个默认构造函数,并添加一个对超类构造函数的调用。因此,您的子类实际上看起来像:

class child extends parent {
 child() {
  super();
 }
}

调用 super() 在基类中寻找零参数构造函数,由于不存在这样的构造函数,因此会出现错误。

情况2中,父父类没有任何构造函数。

int parent(int x) {} 不是构造函数,因为它有一个返回类型。它只是一个具有类名的方法。子类也没有任何构造函数。因此编译器为子类和父类都添加了默认构造函数,并添加了对超类构造函数的调用:

class parent {
 parent() {
  super(); // calls Object class ctor.
 }
  int parent(int x) {} // not a ctor.
}

class child extends parent {
 child() {
  super();
 }
}

19

关于构造函数没有返回类型的问题

构造函数不能有返回类型。根据定义,如果一个方法有返回类型,那么它就不是构造函数。

JLS 8.8 构造函数声明

构造函数用于创建类的实例对象。[名称必须与类名匹配,但除此之外,]在其他方面,构造函数的声明与没有结果类型的方法声明完全相同。


关于默认构造函数

以下代码片段会导致编译错误:

class Parent {
   Parent(int a){}
}

class Child extends Parent{

   // DOES NOT COMPILE!!
   // Implicit super constructor parent() is undefined for default constructor.
   // Must define an explicit constructor

}

原因不是构造函数中的返回类型,而是因为你没有为Child提供任何构造函数,编译器会自动为你创建一个默认构造函数。然而,这个默认构造函数试图调用超类Parent的默认构造函数,但是Parent没有默认构造函数,这就是编译错误的来源
以下是默认构造函数的规范:

JLS 8.8.9 默认构造函数

如果一个类没有构造函数声明,则会自动提供一个不带参数的默认构造函数:

  • 如果正在声明的类是原始类Object,则默认构造函数为空。
  • 否则,默认构造函数不带参数,只是使用无参调用超类构造函数。
以下是一个简单的修复方案:
class Parent {
   Parent(int a){}
}

class Child extends Parent{

   // compiles fine!
   Child() {
      super(42);
   }

}

关于与构造函数同名的方法

以下代码片段可以编译:

// COMPILES FINE!!

class Parent  {

   // method has same name as class, but not a constructor
   int Parent(int a) {
      System.out.println("Yipppee!!!");
      return 42;
   }

   // no explicit constructor, so default constructor is provided
}

class Child extends Parent {

   // no explicit constructor, so default constructor is provided

}

实际上,以上代码片段中没有显式的构造函数。你所拥有的是一个与类名相同的普通方法。虽然允许这样做,但不建议这样做: JLS 8.4 方法声明 一个类可以声明一个与该类或字段、成员类或成员接口具有相同名称的方法,但出于风格的考虑,这种做法是不被鼓励的。
你会发现,如果你创建一个 new Parent()new Child()"Yipppee!!!" 不会被打印到标准输出。由于它不是构造函数,因此在创建时不会调用该方法。

没有类型。父类只是没有一个无参构造函数,这使得一个空的子类(继承自父类)不可能存在。我猜测错误信息说在父类中找不到默认构造函数,或者类似的错误提示 :) - extraneon

5
  • 如果您扩展的类没有默认构造函数,则必须提供调用该超级构造函数的构造函数 - 这就是编译错误的原因,即:

隐式超级构造函数parent()对于默认构造函数未定义。 必须定义一个显式构造函数

  • 如果您添加了返回类型,则不再是构造函数,而是方法,并且上述内容不适用。

将来,请先阅读错误消息,并尝试推理(或查找)其含义。


@Bozho:你让它听起来像是一个微不足道的负面评价,但在我看来,这是一个相当严重的错误。(而将“使用相同参数”更改为“调用该超级构造函数”的做法根本不是“一个错误的单词”)。 - Jon Skeet
@Bozho:当我加载它时,它还没有被修复 :) - Jon Skeet
当然,一开始的负评是应该的,我并没有说它不应该 :) - Bozho
@Bozho:并没有明确表达,但是你原始评论的形式:“我修正了一个错误的单词”在我看来已经暗示了这一点。 - Jon Skeet

2
构造函数不需要返回类型。构造函数被调用来创建该类型的实例。从构造函数“返回”的本质上是一个准备好供使用的该类型实例。

2

构造函数没有返回类型


1

尝试将其更改为:

class parent 
{
parent(int a){}
}

class child extends parent
{
  child(int a){
    super(a);
  }
}

1
从技术上讲,您没有为构造函数添加返回类型,而是将构造函数更改为方法,该方法恰好与类名相同。您应该调用super(int),如下所示:
class parent 
{
parent(int a){}
}

class child extends parent{ child(int a){ super(a); } }

你的代码对于child隐式地尝试做这个:

class child extends parent{ child(){ super(); } }

那就是,它试图调用parent中的一个无参数构造函数,显然这是不可能的,因为它只有一个带有int参数的构造函数。

1

codaddict已经回答了,但是有两个评论。 按照Java代码规范,类名应该以大写字母开头(添加修饰符也很有帮助)。 如果你有编译错误,那就把它放上去,尽管在这种情况下没有必要。


0
你所做的只是通过添加int将“构造函数”转换为具有默认可见性的方法,然后因为你没有指定构造函数,编译时它会自动为你添加一个默认构造函数。
如果你想要编译通过,你必须指定一个默认构造函数,这也是Child类正在寻找的,例如:
  class parent 
    {
      parent(int a){}

      parent(){}
    }

class child extends parent{}

0

1) 最佳实践是使用大写字母开头的类名,以及小写字母开头的方法名。

2) 如果您没有为一个类创建构造函数,则它具有默认的空构造函数。

3) 当继承一个类时,您需要覆盖至少一个它的构造函数,如果您没有指定任何构造函数,则会自动继承空构造函数。

如果子类有调用super(int i)的构造函数,父类没有构造函数(那么它将具有默认的空构造函数),或者父类明确实现了空构造函数,则您提交的代码将起作用。

这将起作用。

public class Parent {
    public Parent(int i) { }
    public Parent() { }
}

public class Child {
}

空的Child类的行为就像它是这样编写的:

public class Child {
    public Child() {
        super();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接