【问题标题】:Chaining Constructors in JavaJava中的链式构造函数
【发布时间】:2019-07-20 11:26:33
【问题描述】:

想不出更好的标题。

经典学习示例:Human 类,其中属性为姓名、年龄、母亲和父亲。父母都是Human

public class Human {
    String name;
    int age;
    Human mother;
}

我想创建 3 个构造函数:

  1. Human();
  2. Human(String name, int age);
  3. Human(String name, int age, Human mother)

我确实了解链接的工作原理,这就是我所做的:

Human() {
    this("Jack", 22);
}

Human(int age, String name) {
    this(age, name, new Human()); // new Human() will cause SOF Error.
}

Human(int age, String name, Human mother) {
    this.age = age;
    this.name = name;
    this.mother = mother;
}

如上所述,我收到了StackOverflowError,我再次我知道为什么会这样了。 虽然公平地说,我想我会得到像人类杰克这样的东西,他的母亲也是人类杰克

不过,我想知道该怎么做。我的猜测是,我应该使用所有参数调用构造函数,而不是 new Human(),但我不确定它是否正确以及唯一可用的选项。

将不胜感激这里的任何指导。

【问题讨论】:

  • new Human() 调用this("Jack", 22) 然后调用new Human(age, name) 然后再次调用new Human()。因此,Stackoverflow。
  • 人类拥有默认值真的有意义吗?

标签: java constructor-overloading constructor-chaining


【解决方案1】:

是的,你说得对,为什么会这样。不过可以肯定的是:

  • new Human() 致电this("Jack", 22)
  • this("Jack", 22) 致电this(age, name, new Human())
  • 再次调用this("Jack", 22)中的new Human()
  • 再次调用this(age, name, new Human())
  • 直到你用完堆栈

正确的做法是确保您不会回到起点。因此,如果您在任何构造函数中使用new Human(String)new Human(String, int),则必须确保该构造函数(new Human(String)new Human(String, int))也不会使用new Human(String)new Human(String, int),因为您'最终会无休止地递归。您需要在某处使用new Human(String, int, Human)。比如:

Human(int age, String name) {
    this(age, name, null);
}

当然,这意味着新实例将具有null 对应于mother

【讨论】:

  • 这是一个很好的答案!感谢您的帮助。
【解决方案2】:

如果我正确理解您的问题,有两个子问题:

  1. Java 语言(使用构造函数)是否有不同的方法?
  2. 在面向对象设计中有更好的方法吗?

关于第一个问题,构造函数是一个方法,你的实现会产生两个递归方法。您必须打破递归或引入退出条件。 另一个选项 - 在第一个构造函数中调用 this(age, name, null)

关于第二个问题,一个流行的解决方案是simple factory 模式,在这种模式下,您只有一个带有所有参数的 private 构造函数,然后是一些公共工厂方法来做任何您想做的事情。

【讨论】:

  • 谢谢,这是一个很好的答案!需要了解有关simple factory 解决方案的更多信息。
【解决方案3】:
Human() {
    this.name = "Jack";
    this.age = 22;
}

Human(int age, String name) {
    this.age = age;
    this.name = name;
    this.mother = null;
}

Human(int age, String name, Human mother) {
    this.age = age;
    this.name = name;
    this.mother = mother;
}

这不会创建任何分层或嵌套的构造函数

【讨论】:

    【解决方案4】:

    您的构造函数 Human(int, String) 会在没有任何条件的情况下进行递归,最后会创建一个 StackOverflowError

    构造函数重载是一种非常常见的方法,可以提供方便的方法来创建对象。只要成员不是final 并且以后可能会被操作,您最好不要传递任何值(又名null),而不是动态创建更多对象。

    实际上,没有一个人没有母亲,但它可能是未知的,所以现在通过null 将是更好的方法。

    如果您需要 mother 不可变对象,则不得提供任何没有母亲参考的构造函数以使其清晰可见。即使这样也行不通,因为你无法为人类的开端提供如此无尽的树状结构。通常,此类结构有一个“根”对象,该对象没有父对象(在本例中为 mother)。

    【讨论】:

    • 欣赏如此详细的回答!
    【解决方案5】:

    我建议不要使用构造函数链接。我更喜欢使用变量链接和使用构建器设计模式以及节点类型的数据结构。

    Class Human{
    int age;
    Sting name;
    Human mother;
    
    public  Human setAge(int age){
    this.age = age;    
    return this;
    }
    
    public Human setName(String name){
    this.name = name;
    return this;
    }
    
    public Human setHuman(Human mother){
    this.mother= mother;
    return this;
    }
    
    }
    

    完成此操作后,您可以将第一个 Mother 实例创建为人类,然后在 child 中设置为人类。让我知道更具体的答案。

    【讨论】:

    • 这是一种新方法!谢谢。
    • 这种方法也有 Lambok jar 版本。如果您有兴趣,那么将提供有关 lambok jar 的更多详细信息
    猜你喜欢
    • 1970-01-01
    • 2017-01-03
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多