为什么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中,不需要它,因为对象没有子对象,只有指向其他对象的指针。

这是我的问题:

  1. 他们是什么意思,“因为物体没有子物体?” 我不明白一个子对象是什么(我试图查找它); 它们是指一个扩展超类的子类的实例吗?

  2. 至于为什么Java没有像C ++这样的初始化器列表,我会假定原因是因为所有的字段在Java中已经被默认初始化了,而且因为Java使用super关键字来调用super(或者C ++术语中的base)-class构造函数。 它是否正确?

在C ++中,初始化程序列表是必需的,因为有几种语言function不是在Java中存在,就是在Java中以不同的方式工作:

  1. const :在C ++中,可以定义一个标记为const的字段,该字段不能被赋值,并且必须在初始化程序列表中初始化。 Java确实有final字段,但您可以分配给构造函数体中的final字段。 在C ++中,分配给构造const中的const字段是非法的。

  2. 参考 :在C ++中,引用(而不是指针)必须被初始化以绑定到某个对象。 创build没有初始化程序的引用是非法的。 在C ++中,您指定的方式是使用初始化程序列表,因为如果您在未初始化的情况下引用构造方法的主体中的引用,那么您将使用未初始化的引用。 在Java中,对象引用的行为与C ++指针类似,可以在创build后分配。 他们只是默认为null否则。

  3. 直接子对象 。 在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中抛出的模常量,从基类重载的方法调用等