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

bvjxkvbb  于 2022-12-24  发布在  Java
关注(0)|答案(3)|浏览(202)

在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.他们所说的"因为对象没有子对象"是什么意思?我不明白什么是子对象(我试着去查了一下);它们是指子类的示例化来扩展超类吗?
1.至于为什么Java没有像C
那样的初始化列表,我认为原因是因为Java默认情况下所有字段都已经初始化了,而且Java使用了super关键字来调用super(或C++术语中的base)类构造函数,这对吗?

44u64gxh

44u64gxh1#

在C中,初始化器列表是必需的,因为有一些语言特性在Java中不存在,或者在Java中工作方式不同:
1.* * 一月一日**:在C
中,您可以定义标记为const的字段,这些字段不能赋值,必须在初始化列表中初始化。Java确实有final字段,但您可以在构造函数的主体中赋值给final字段。在C中,在构造函数中赋值给const字段是非法的。
1.* * 参考文献**:C
中的引用(相对于指针)必须被初始化才能绑定到某个对象。没有初始化式就创建引用是非法的。在C中,指定它的方法是使用初始化式列表,因为如果你在构造函数体中引用引用而没有首先初始化它,你将使用一个未初始化的引用。在Java中,对象引用的行为类似于C指针,可以在创建后赋值给。否则,它们只是默认为null
1.* * 直接子对象**。在C中,对象可以直接包含作为字段的对象,而在Java中,对象只能包含对这些对象的 * 引用 *。也就是说,在C中,如果您声明一个包含string作为成员的对象,则该字符串的存储空间将直接构建到对象本身的空间中。而在Java中,你只需要为存储在其他地方的String对象的引用获取空间。因此,C需要提供一种方法来为这些子对象赋予初始值,否则它们将保持未初始化状态。默认情况下,它使用这些类型的默认构造函数。但是如果你想使用不同的构造函数或者没有默认的构造函数,初始化器列表会给你一个方法来绕过这个问题,在Java中,你不需要担心这个问题,因为引用默认为null,然后你可以赋值给它们去引用你真正想让它们引用的对象,如果你想使用非默认的构造函数,那么你不需要任何特殊的语法只需设置对通过适当的构造函数初始化的新对象的引用。
在Java可能需要初始化列表的少数情况下(例如,调用超类构造函数或为其字段提供默认值),这是通过另外两个语言特性来处理的:调用超类构造函数的super关键字,以及Java对象可以在声明它们的时候给它们的字段默认值的事实。由于C
有多重继承,只有一个super关键字不会明确地引用一个基类,在C11之前,C不支持类中的默认初始化器,而必须依赖于初始化器列表。

m1m5dgzv

m1m5dgzv2#

** 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();
tquggr8v

tquggr8v3#

因为Java不需要它们来初始化类型没有零值的字段。
在C++中

class C {
  D d;
}

如果没有d的成员初始化器,D::D()将被调用,这使得在D没有零类型时无法初始化字段。当D::D()被显式声明为private时,会发生这种情况。
在Java中,所有引用类型都有一个已知的零值null,因此字段总是可以初始化的。
Java也做了大量的工作来确保 * 所有final字段在第一次使用之前和构造函数结束之前都被初始化,所以尽管Java有一个类似C++的const字段初始化需求,但它只是在构造函数体中重载this.fieldName = <expression>来表示字段初始化。

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

相关问题