繁体   English   中英

为什么Java没有像C ++那样的初始化列表?

[英]Why doesn't Java have initializer lists like in C++?

在C ++中,您可以使用初始化列表在构造函数开始运行之前初始化类的字段。 例如:

Foo::Foo(string s, double d, int n) : name(s), weight(d), age(n) {
    // Empty; already handled!
}

我很好奇为什么Java没有类似的功能。 根据Core Java:第1卷

C ++使用这种特殊语法来调用字段构造函数。 在Java中,不需要它,因为对象没有子对象,只有指向其他对象的指针。

这是我的问题:

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

  2. 至于为什么Java没有像C ++这样的初始化列表,我认为原因是因为所有字段在Java中都已默认初始化,并且因为Java使用super关键字来调用super(或C ++语言中的基类)类构造函数。 它是否正确?

在C ++中,初始化程序列表是必需的,因为Java中不存在或在Java中以不同方式工作的一些语言功能:

  1. const :在C ++中,您可以定义标记为const的字段,这些字段无法分配,并且必须在初始化列表中初始化。 Java确实有final字段,但您可以分配给构造函数体中的final字段。 在C ++中,分配给构造const中的const字段是非法的。

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

  3. 直接子对象 在C ++中,对象可以直接将对象包含为字段,而在Java对象中只能包含对这些对象的引用 也就是说,在C ++中,如果声明一个具有string作为成员的对象,则该string的存储空间将直接构建到对象本身的空间中,而在Java中,您只需获取空间以引用其他String对象存储在别处。 因此,C ++需要为您提供一种方法来为这些子对象提供初始值,否则它们将保持未初始化状态。 默认情况下,它使用这些类型的默认构造函数,但是如果您想使用不同的构造函数或者没有默认构造函数可用,则初始化程序列表为您提供了绕过此方法的方法。 在Java中,您不必担心这一点,因为引用将默认为null ,然后您可以指定它们以引用您实际希望它们引用的对象。 如果你想使用非默认的构造函数,那么你不需要任何特殊的语法; 只需将引用设置为通过适当的构造函数初始化的新对象。

在Java可能需要初始化列表的少数情况下(例如,调用超类构造函数或为其字段赋予默认值),这可以通过另外两种语言特性来处理:调用超类构造函数的super关键字以及Java对象的事实可以在声明它们的位置给出它们的字段默认值。 由于C ++具有多重继承,因此只有一个super关键字不会明确地引用单个基类,而在C ++ 11之前,C ++不支持类中的默认初始值设定项,并且必须依赖于初始化列表。

希望这可以帮助!

C ++

两者之间有区别

ClassType t(initialization arguments);

ClassType * pt;

后者不需要初始化(设置为NULL)。 前者确实如此。 把它想象成一个整数。 没有值就没有int, 但是你可以有一个没有值的int指针。

所以当你有:

class ClassType
{
    OtherClass value;
    OtherClass * reference;
};

然后声明:

ClassType object;

自动在value创建OtherClass的实例。 因此,如果OtherClass已初始化,则必须在ClassType构造函数中完成。 但是, reference只是一个指针(内存中的地址),可以保持未初始化状态。 如果你想要一个OtherClass的实例,你必须使用

object.reference = new OtherClass(initialization arguments);

Java的

只有

class ClassType
{
    OtherClass reference;
}

这相当于C ++中的指针。 在这种情况下,你这样做:

ClassType object = new ClassType();

您不会自动创建OtherClass的实例。 因此,除非您愿意,否则不必在构造函数中初始化任何内容。 当你想要一个OtherClass的对象时,你可以使用

object.reference = new OtherClass();

因为Java不需要它们来允许初始化类型没有零值的字段。

在C ++中

class C {
  D d;
}

如果没有d的成员初始值设定项,将调用D::D() ,如果D没有零类型,则无法初始化该字段。 D::D()显式声明为private时,就会发生这种情况。

在Java中,所有引用类型都有一个已知的零值 null ,因此可以始终初始化字段。

Java还做了很多工作来确保所有final字段在第一次使用之前和构造函数结束之前都已初始化,因此虽然Java有像C ++的const字段初始化要求这样的要求,但它只是重载this.fieldName = <expression> in构造函数体意味着字段初始化。

  • :在ctor中抛出的modulo异常,从基类重写的方法调用等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM