【问题标题】:Can we have a return type for a constructor in Java?我们可以在 Java 中为构造函数设置返回类型吗?
【发布时间】:2010-08-17 11:03:23
【问题描述】:

以下代码给出编译错误:

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{}

我读过构造函数不应该有返回类型,这显然不是一直正确的。所以我的问题是我们什么时候应该有构造函数的返回类型?

【问题讨论】:

  • 您缺少public 访问修饰符,不是吗?
  • 这样想可能更容易一些:如果它有返回类型,它就不是构造函数,它是一个方法。
  • 以后,永远不要说“编译错误”,只说“编译错误并带有消息'yabba dabba'”。您不应忽略该消息,它会说明问题的原因。
  • 实际上,伙计们,这个问题毕竟有一些优点。投票重新开放。对不起,我在那里太仓促了。
  • 您可以将构造函数视为具有当前类名的返回类型,但没有方法名,如果这样更容易的话。

标签: java constructor


【解决方案1】:

案例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();
 }
}

【讨论】:

    【解决方案2】:

    在没有返回类型的构造函数上

    构造函数不能有返回类型。根据定义,如果方法具有返回类型,则它不是构造函数。

    JLS 8.8 Constructor Declarations

    构造函数用于创建作为类实例的对象。 [名称必须与类名匹配,但是]在所有其他方面,构造函数声明看起来就像没有结果类型的方法声明。


    关于默认构造函数

    下面的 sn-p 确实给出了编译错误:

    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提供ANY构造函数,所以会自动创建一个默认构造函数由编译器为您服务。然而,这个默认构造函数试图调用超类Parent 的默认构造函数,而 NOT 有一个默认构造函数。 那是编译错误的来源。

    这是默认构造函数的规范:

    JLS 8.8.9 Default Constructor

    如果类不包含构造函数声明,则自动提供不带参数的默认构造函数

    • 如果声明的类是原始类Object,则默认构造函数的主体为空。
    • 否则,默认构造函数不带参数,只是调用不带参数的超类构造函数。

    以下是一个简单的修复:

    class Parent {
       Parent(int a){}
    }
    
    class Child extends Parent{
    
       // compiles fine!
       Child() {
          super(42);
       }
    
    }
    

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

    下面的 sn -p DOES 编译:

    // 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
    
    }
    

    上面的sn-p中其实没有显式构造函数。你所拥有的是一个与类同名的常规方法。这是允许的,但不鼓励这样做:

    JLS 8.4 Method Declarations

    class 可以声明与 class 或字段、成员 class 或成员 interface 同名的方法,但出于风格问题不鼓励这样做。

    您会发现,如果您创建 new Parent()new Child()"Yipppee!!!"不会打印到标准输出。该方法在创建时不会被调用,因为它不是构造函数。

    【讨论】:

    • 没有类型。 Parent 只是没有无参数构造函数,这使得空子(扩展父)类成为不可能。我的猜测是错误说在父级中找不到默认构造函数,或者类似的:)
    【解决方案3】:
    • 当您扩展一个没有默认构造函数的类时,您必须提供一个调用该超级构造函数的构造函数 - 这就是编译错误的原因,即:

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

    • 添加返回类型时,this 不再是构造函数,而是方法,上述不适用

    以后先阅读错误信息,并尝试推理(或找出)它的含义。

    【讨论】:

    • @Bozho:你说得好像这是一个小小的反对票——这是一个非常严重的错误,IMO。 (无论如何,将“使用相同的参数”更改为“调用该超级构造函数”几乎不是“一个错误的词”。)
    • @Bozho:当我加载它时它没有修复:)
    • 当然,最初的反对票是应得的,我没说不是:)
    • @Bozho:没有明确说明 - 但您评论的原始形式:“我修正了一个错误的词”几乎暗示了它,IMO。
    【解决方案4】:

    构造函数没有有返回类型。调用构造函数来创建该类型的实例。本质上,从构造函数“返回”的是该类型的实例,可供使用。

    【讨论】:

      【解决方案5】:

      构造函数没有任何返回类型

      【讨论】:

        【解决方案6】:

        尝试将其更改为:

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

        【讨论】:

          【解决方案7】:

          从技术上讲,您没有向构造函数添加返回类型,而是将构造函数更改为恰好与类同名的方法。你应该做的是调用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 参数。

          【讨论】:

            【解决方案8】:

            codaddict 已经回答了,但有两个 cmets。 按照 java 代码约定,类应该以大写开头(添加修饰符也很有帮助)。 如果你有编译错误,那就把它说出来,没有它,这里的情况就很清楚了。

            【讨论】:

              【解决方案9】:

              通过添加 int 所做的只是将“构造函数”转换为具有默认可见性的方法,然后由于您没有指定构造函数,它只会在编译时为您添加默认构造函数。

              如果你想让它编译,你必须指定一个默认构造函数,这是 Child 类正在寻找的,例如:

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

              【讨论】:

                【解决方案10】:

                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();
                    }
                }
                

                【讨论】:

                  【解决方案11】:

                  构造函数没有返回类型。构造函数返回该类型的实例。构造函数的名称应与类的名称相同。

                  【讨论】:

                    猜你喜欢
                    • 2015-06-21
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-01-31
                    • 1970-01-01
                    • 2015-05-22
                    • 2016-04-22
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多