问题描述
在 C++ 中,您可以使用初始化列表在构造函数开始运行之前初始化类的字段.例如:
In C++, you can use an initializer list to initialize the class's fields before the constructor begins running. For example:
Foo::Foo(string s, double d, int n) : name(s), weight(d), age(n) {
// Empty; already handled!
}
我很好奇为什么 Java 没有类似的功能.根据Core Java:第 1 卷:
I am curious why Java does not have a similar feature. According to Core Java: Volume 1:
C++ 使用这种特殊的语法来调用字段构造函数.在 Java 中,不需要它,因为对象没有子对象,只有指向其他对象的指针.
这是我的问题:
因为对象没有子对象"是什么意思?我不明白什么是子对象(我试着查了一下);它们是指扩展超类的子类的实例化吗?
What do they mean by "because objects have no subobjects?" I don't understand what a subobject is (I tried looking it up); do they mean an instantiation of a subclass which extends a superclass?
至于为什么Java没有像C++这样的初始化列表,我认为原因是因为Java中所有字段都已经默认初始化了,也因为Java使用了super
关键字调用超(或 C++ 术语中的基)类构造函数.这是正确的吗?
As for why Java does not have initializer lists like C++, I would assume that the reason is because all fields are already initialized by default in Java and also because Java uses the super
keyword to call the super(or base in C++ lingo)-class constructor. Is this correct?
推荐答案
在 C++ 中,初始化列表是必要的,因为 Java 中不存在一些语言特性,或者在 Java 中工作方式不同:
In C++, initializer lists are necessary because of a few language features that are either not present in Java or work differently in Java:
const
:在C++中,可以定义一个标记为const
的字段,不能赋值,必须初始化在初始化列表中.Java 确实有final
字段,但您可以在构造函数的主体中分配给final
字段.在 C++ 中,分配给构造函数中的const
字段是非法的.
const
: In C++, you can define a fields that are markedconst
that cannot be assigned to and must be initialized in the initializer list. Java does havefinal
fields, but you can assign tofinal
fields in the body of a constructor. In C++, assigning to aconst
field in the constructor is illegal.
引用:在 C++ 中,引用(相对于指针)必须初始化才能绑定到某个对象.在没有初始化程序的情况下创建引用是非法的.在 C++ 中,您指定它的方式是使用初始化列表,因为如果您要在构造函数主体中引用引用而不首先对其进行初始化,那么您将使用未初始化的引用.在 Java 中,对象引用的行为类似于 C++ 指针,可以在创建后分配.他们只是默认为 null
否则.
References: In C++, references (as opposed to pointers) must be initialized to bind to some object. It is illegal to create a reference without an initializer. In C++, the way that you specify this is with the initializer list, since if you were to refer to the reference in the body of the constructor without first initializing it you would be using an uninitialized reference. In Java, object references behave like C++ pointers and can be assigned to after created. They just default to null
otherwise.
直接子对象.在 C++ 中,一个对象可以直接包含作为字段的对象,而在 Java 中,对象只能保存对这些对象的 引用.也就是说,在 C++ 中,如果您声明一个具有 string
作为成员的对象,则该字符串的存储空间直接构建到对象本身的空间中,而在 Java 中您只需获得空间用于引用存储在其他地方的其他一些 String
对象.因此,C++ 需要为您提供一种方法来赋予这些子对象初始值,否则它们将保持未初始化状态.默认情况下,它使用这些类型的默认构造函数,但如果您想使用不同的构造函数或没有可用的默认构造函数,初始化列表为您提供了一种绕过它的方法.在 Java 中,您不必担心这一点,因为引用将默认为 null
,然后您可以将它们分配给您实际希望它们引用的对象.如果要使用非默认构造函数,则不需要任何特殊语法;只需将引用设置为通过适当的构造函数初始化的新对象.
Direct subobjects. In C++, an object can contain object directly as fields, whereas in Java objects can only hold references to those objects. That is, in C++, if you declare an object that has a string
as a member, the storage space for that string is built directly into the space for the object itself, while in Java you just get space for a reference to some other String
object stored elsewhere. Consequently, C++ needs to provide a way for you to give those subobjects initial values, since otherwise they'd just stay uninitialized. By default it uses the default constructor for those types, but if you want to use a different constructor or no default constructor is available the initializer list gives you a way to bypass this. In Java, you don't need to worry about this because the references will default to null
, and you can then assign them to refer to the objects you actually want them to refer to. If you want to use a non-default constructor, then you don't need any special syntax for it; just set the reference to a new object initialized via the appropriate constructor.
在 Java 可能需要初始化列表的少数情况下(例如,调用超类构造函数或为其字段提供默认值),这是通过其他两个语言特性来处理的:super
关键字调用超类构造函数,以及 Java 对象可以在声明它们的位置为其字段提供默认值这一事实.由于 C++ 具有多重继承,因此只有一个 super
关键字不会明确引用单个基类,并且在 C++11 之前,C++ 不支持类中的默认初始值设定项,因此必须依赖于初始化列表.
In the few cases where Java might want initializer lists (for example, to call superclass constructors or give default values to its fields), this is handled through two other language features: the super
keyword to invoke superclass constructors, and the fact that Java objects can give their fields default values at the point at which they're declared. Since C++ has multiple inheritance, just having a single super
keyword wouldn't unambiguously refer to a single base class, and prior to C++11 C++ didn't support default initializers in a class and had to rely on initializer lists.
希望这会有所帮助!
这篇关于为什么 Java 没有像 C++ 中那样的初始化列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!