其实我也不太清楚循环定义具体什么意思。
我的意思是指这个:class A {
// ...
public void go() {
A a = new A();
// ...
}
// ...
}虽然能编译通过。但是让人费解,定义类A的时候就用到了它本身!(有点像递归)
估计我的表达也有点费解,有人看明白没
我的意思是指这个:class A {
// ...
public void go() {
A a = new A();
// ...
}
// ...
}虽然能编译通过。但是让人费解,定义类A的时候就用到了它本身!(有点像递归)
估计我的表达也有点费解,有人看明白没
我现在要定义一个类A,它由go()等几个方法组成,其中方法go()的定义又用到了A,这时候我们得知道A是什么吧。
问题是这时候A的定义还不完整(还在定义的过程中)。连它是什么都还没弄清楚怎么就拿来直接使用了呢?
给人感觉是逻辑上的无限循环(有点像那个鸡和蛋的问题)。
,这样一来,类的方法里出现本类的对象就不会引起语义的含混不清,因此是没有任何问题的。
A a = new A();
}但是,类没有被定义完整确实是不能够被实例化的!
那为什么上面代码被允许?请见下文。
在C++中,类成员不能是自身的对象。原因就是类没有被定义完整是不能够被实例化的,否则就是楼主说的那样,我要有A的对象做成员,可A我还没有定义完就实例,这样岂不是递归下去了...
所以在C++中你不能这样:class A {
A a;
};但却可以这样:class A {
A *a; //或者A &a;也行
};类成员变量只能是自己类对象的指针或者应用。
好,那么我们将构造函数写上,从而使类定义完整(如果不写,编译器也会为我们造一个差不多功能的默认构造器):class A {
A *a;
A():a(new A()) {}
};好了,或许楼主通过以上的代码已经大概了解原因了。在构造函数中,可以对a指针进行初始化,因为此时类已经定义完整(构造函数是在类定义完后才运行的)。
而在Java中,除了8种基本类型外,其他都是引用类型。所以在Java中这样写:A a;相当于在C++中这样写:A &a;。所以在A类中保存的只是自己类型对象的引用值。
而又由于Java比较奇葩的构造方式,也就是可以直接给类成员赋值初始化,而不是通过构造函数。所以可以这样写:class A {
A a = new A(); //这里不会在类定义时执行,而是等到构造对象时才被执行!
}所以,上面那样写给人感觉比较乱。还不如在构造函数里写的清楚。所以我讨厌Java!