为什么Java没有像C ++那样的初始化列表?
在C ++中,可以使用初始化程序列表在构造函数开始运行之前初始化类的字段。 例如:
Foo::Foo(string s, double d, int n) : name(s), weight(d), age(n) { // Empty; already handled! }
我很好奇为什么Java没有类似的function。 根据核心Java:第1卷 :
C ++使用这个特殊的语法来调用字段构造函数。 在Java中,不需要它,因为对象没有子对象,只有指向其他对象的指针。
这是我的问题:
-
他们是什么意思,“因为物体没有子物体?” 我不明白一个子对象是什么(我试图查找它); 它们是指一个扩展超类的子类的实例吗?
-
至于为什么Java没有像C ++这样的初始化器列表,我会假定原因是因为所有的字段在Java中已经被默认初始化了,而且因为Java使用
super
关键字来调用super(或者C ++术语中的base)-class构造函数。 它是否正确?
在C ++中,初始化程序列表是必需的,因为有几种语言function不是在Java中存在,就是在Java中以不同的方式工作:
-
const
:在C ++中,可以定义一个标记为const
的字段,该字段不能被赋值,并且必须在初始化程序列表中初始化。 Java确实有final
字段,但您可以分配给构造函数体中的final
字段。 在C ++中,分配给构造const
中的const
字段是非法的。 -
参考 :在C ++中,引用(而不是指针)必须被初始化以绑定到某个对象。 创build没有初始化程序的引用是非法的。 在C ++中,您指定的方式是使用初始化程序列表,因为如果您在未初始化的情况下引用构造方法的主体中的引用,那么您将使用未初始化的引用。 在Java中,对象引用的行为与C ++指针类似,可以在创build后分配。 他们只是默认为
null
否则。 -
直接子对象 。 在C ++中,对象可以直接作为字段包含对象,而在Java对象中只能包含对这些对象的引用 。 也就是说,在C ++中,如果声明一个
string
作为成员的对象,则该string
的存储空间将直接构build到对象本身的空间中,而在Java中,您只需获得用于引用其他String
对象存储在别处。 因此,C ++需要为你提供一个给子对象初始值的方法,否则它们会保持未初始化状态。 默认情况下,它使用这些types的默认构造函数,但是如果您想使用不同的构造函数或者没有默认构造函数可用,则初始化程序列表将为您提供绕过的方法。 在Java中,您不必担心这个问题,因为引用将默认为null
,然后可以将它们分配给您实际上希望它们引用的对象。 如果你想使用非默认的构造函数,那么你不需要任何特殊的语法; 只需将引用设置为通过相应的构造函数初始化的新对象即可。
在less数情况下,Java可能需要初始化列表(例如,调用超类构造函数或给它的字段默认值),这是通过其他两种语言特性来处理的: super
关键字来调用超类的构造函数,以及Java对象可以在声明它们的位置给它们的字段默认值。 由于C ++具有多重inheritance,只有一个super
关键字不会明确指向一个基类,并且在C ++ 11之前,C ++不支持类中的默认初始值设定项,并且必须依赖初始值设定项列表。
希望这可以帮助!
C ++
之间有区别
ClassType t(initialization arguments);
和
ClassType * pt;
后者不需要初始化(设置为NULL)。 前者呢。 把它看作一个整数。 你不能有一个没有值的int, 但是你可以有一个没有值的int指针。
所以当你有:
class ClassType { OtherClass value; OtherClass * reference; };
然后声明:
ClassType object;
自动创build一个value
OtherClass
的实例。 因此,如果OtherClass
有初始化,它必须在ClassType
构造函数中完成。 然而, reference
只是一个指针(内存中的地址),可以保持未初始化。 如果你想要一个OtherClass
的实例,你必须使用
object.reference = new OtherClass(initialization arguments);
Java的
只有
class ClassType { OtherClass reference; }
这相当于C ++中的一个指针。 在这种情况下,当你这样做时:
ClassType object = new ClassType();
您不会自动创buildOtherClass
的实例。 因此,除非需要,否则不必在构造方法中初始化任何内容。 当你想要一个OtherClass
的对象时,你可以使用它
object.reference = new OtherClass();
因为Java不需要它们允许初始化types没有零值的字段。
在C ++中
class C { D d; }
如果没有用于d
的成员初始化程序,那么将调用D::D()
,这使得如果D
没有零types,就不可能初始化该字段。 当D::D()
被显式声明为private
时,可能会发生这种情况。
在Java中,所有引用types都有一个零值 ,所以一个字段总是可以被初始化。
Java也做了一大堆工作来确保所有的final
字段在第一次使用之前和构造函数结束之前都被初始化,所以当Java有像C ++的const
字段初始化要求那样的要求时,它只是重载this.fieldName = <expression>
in构造函数体是指字段初始化。
- :在ctor中抛出的模常量,从基类重载的方法调用等