12

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

编码:

public class Test2{
    private Test2 subject = new Test2(); //Create Test2 object in Test2
    private int num;
}

问题:

  1. 为什么 Java 允许执行上述代码,而 C++ 不允许?

  2. 上面的代码是否创建了无限数量的对象?因为Test2它本身包含一个Test2对象,该对象又包含一个Test2对象,该对象本身具有一个Test2对象,依此类推。

4

6 回答 6

18

关于您的问题,两种语言之间的主要区别在于 Java 是一种具有引用语义的语言(原始类型除外),而 C++ 是一种具有值语义的语言,允许通过引用和指针进行引用语义。

在两种语言中看起来相似的语法具有完全不同的含义,在 Java 中创建引用( Test2 x = new Test2();) 时,C++ 中的等效构造将使用指针 ( Test2 *x = new Test2();)。

一个关键的区别是,通过使用指针在值语义之上提供引用语义很简单,但在(纯)引用语义之上提供值语义是不可能的。该语句的一些含义包括无法控制 Java 中对象在内存中的布局或数据的局部性(对于原始类型和原始类型数组以外的任何内容),而在另一个方向上可以更好地控制对象在 C++ 中允许您模仿 Java 对象。

于 2012-11-28T15:08:28.667 回答
14

关于问题 2 - 如果您运行此代码,您会得到一个 StackOverflowException => 是的,它会创建无限数量的对象(它会尝试...)

public class Test2 {

    private Test2 subject = new Test2(); //Create Test2 object in Test2

    public static void main(String[] args) throws Exception {
        Test2 t = new Test2();
    }
}
于 2012-11-28T14:48:06.003 回答
4

subject这是Test2. 如果您尝试运行它,代码将很快耗尽一些资源(可能是堆栈空间,也可能是堆空间)。

于 2012-11-28T14:47:01.617 回答
3

为什么 Java 允许执行上述代码而 C++ 不允许?

自 2011 年以来,C++ 还允许在其声明中初始化类成员。

但是,它不允许这种情况:您只能实例化完整类型,并且类类型在类定义中是不完整的,因此必须在构造函数中初始化它,或者通过调用函数:

class Test;
Test * make_test();

class Test {
    // Test is incomplete, so "new Test" is not possible here
    Test * test = make_test();
};

// Test is complete, so we can instantiate it here
Test * make_test() {return new Test;}

Java 没有不完整类型的概念,因此可以在允许实例化任何类的任何地方实例化该类。

上面的代码是否创建了无限对象?

是的,尝试实例化这样的类会使您的程序陷入递归死亡螺旋。

于 2012-11-28T14:57:40.537 回答
0

如果您声明subject为 being static,您将获得单例模式的急切初始化版本,这不会让您耗尽资源。

于 2012-11-28T14:49:12.210 回答
0

因为您可以有多个构造函数,所以它是允许的。如果您只有一个构造函数,这确实会导致无限循环。

public class Test{
    private Test a;

    public Test(String s){
        this.a=new Test();
    }

    public Test(){

    }

}
于 2012-11-28T14:49:24.740 回答