一个类如何拥有自己类型的成员,这不是无限递归吗?

jas*_*son 44 java oop class

假设我定义了一个类,该类具有与其自身相同类型的变量作为成员.

public class abc {
    private abc p;
}
Run Code Online (Sandbox Code Playgroud)

这实际上是有效的,令我惊讶.

为什么我认为它不应该:创建一个实例abc,它包含一个类型的变量abc,其中包含一个类型的变量abc,其中包含一个类型的变量abc,其中.....

显然我错了,有人可以告诉我如何?

Hov*_*els 36

您只是声明变量而不是创建变量.尝试在声明或构造函数中创建它,让我知道会发生什么:

public class Abc {
   private Abc p = new Abc(); // have fun!

   public static void main(String[] args) {
      new Abc();
   }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您不在类中创建它,而是在getter方法或构造函数参数中接受对它的引用,那么您的代码将正常工作.这是一些链表的工作方式.

  • 任何寻求正确答案的人都应该看看[来自@DavidRodríguez - dribe]的答案(http://stackoverflow.com/questions/13607757/object-of-the-class-as-instance-variable-inside -the-class?lq = 1#answer-13608203),其中HovercraftFullOfEels自己赞成. (2认同)

pse*_*ble 20

不同之处在于编译时与运行时检查.

在第一种情况(编译时)中,您声明abc在此实例中将引用type的值.编译器在检查正确的语义时会意识到这一点,并且因为它在编译时知道类型,所以它没有看到这个问题.

在第二种情况(运行时)中,您实际上将为此引用创建一个值以供参考.这是您可能遇到麻烦的地方.例如,如果您说以下内容:

public class abc {
    private abc p;

    public abc() {
        p = new abc();
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能会因为您引用的确切原因而导致您遇到麻烦(递归不包含基本情况,并且会在您从堆空间中运行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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是完全有效的,因为您只创建了一个新的值实例,并且由于运行时已经加载了类,因此它将知道实例变量的类型是有效的.

  • 你的答案确实很有帮助.谢谢道格. (3认同)

rin*_*rer 10

当您想要为某些真实场景建模时,您可能必须使用此概念.例如,想一下Tree的分支.树的分支可能有n个分支.或者从计算机科学背景中,想一下链表的节点.节点将引用其旁边的节点.最后,next将包含一个null以指示列表的结尾.

所以,这只是一个引用,表明这种类型可能引用它自己的一种.而已.