在 Java 中链接构造函数



想不出更好的标题。

一个经典的学习示例:类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)
  • this("Jack", 22)呼叫this(age, name, new Human())
  • 其中的new Human()再次召唤this("Jack", 22)
  • 再次召唤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

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

  1. Java语言(使用构造函数(中是否有其他方法可以做到这一点?
  2. 在面向对象设计中是否有更好的方法?

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

对于第二个问题,一个流行的解决方案是simple factory模式,其中你只有一个带有所有参数的私有构造函数,然后是一些公共工厂方法来做任何你想做的事情。

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

这不会创建任何平坦或嵌套构造函数

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

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

实际上,没有母亲就没有人类,但可能未知,因此暂时通过null将是更好的方法。

如果你需要母体不可变,你一定不能在没有引用的情况下提供任何构造函数,让母体使其清晰可见。即使这样也行不通,因为你无法为人类的开始提供如此无穷无尽的树结构。通常,此类结构具有没有父对象(或本例中的父对象(的"根">对象

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

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

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

最新更新