一个类怎么能有自己类型的成员,这不是无限递归吗?
假设我定义了一个类,该类的成员具有与自身相同类型的变量。
public class Abc {
private Abc p;
}
这实际上有效,令我惊讶。
为什么我认为它不应该:创建一个实例,它包含一个类型的变量,其中包含一个类型的变量,其中包含一个类型的变量,它.....Abc
Abc
Abc
Abc
显然我错了,有人可以启发我怎么做吗?
假设我定义了一个类,该类的成员具有与自身相同类型的变量。
public class Abc {
private Abc p;
}
这实际上有效,令我惊讶。
为什么我认为它不应该:创建一个实例,它包含一个类型的变量,其中包含一个类型的变量,其中包含一个类型的变量,它.....Abc
Abc
Abc
Abc
显然我错了,有人可以启发我怎么做吗?
您只是在声明变量,而不是创建它。尝试在声明或构造函数中创建它,并让我知道会发生什么:
public class Abc {
private Abc p = new Abc(); // have fun!
public static void main(String[] args) {
new Abc();
}
}
顺便说一句,如果您不在类中创建它,而是在 getter 方法或构造函数参数中接受对它的引用,则代码将正常工作。这就是一些链表的工作方式。
区别在于编译时检查与运行时检查。
在第一种情况下(编译时),您声明在此实例中将具有对类型值的引用。编译器在检查正确的语义时会意识到这一点,并且由于它在编译时知道类型,因此它认为这没有问题。Abc
在第二种情况下(运行时),您实际上将为此引用创建一个值。这是你可能会给自己带来麻烦的地方。例如,如果您说了以下几句话:
public class Abc {
private Abc p;
public Abc() {
p = new Abc();
}
}
这可能会导致你陷入麻烦,原因正是你所引用的原因(不包含基本情况的递归,并且会不断分配内存,直到你运行 VM 的堆空间)。
但是,您仍然可以执行与此类似的操作,并避免无限递归。通过避免在构造期间创建值,可以将其推迟到调用方法之前。事实上,这是在 Java 中实现单例模式的常用方法之一。例如:
public class Abc {
private Abc p;
private Abc() { // Private construction. Use singleton method
}
public static synchronized Abc getInstance() {
if (p == null)
p = new Abc();
return p;
}
}
这是完全有效的,因为您只创建该值的一个新实例,并且由于运行时已经加载了该类,因此它将知道实例变量的类型是有效的。