当前位置: 首页 > 面试题库 >

Java为什么没有C ++中的初始化列表?

施海
2023-03-14
问题内容

在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 lingo中的基)类构造函数。这样对吗?


问题答案:

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

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

  2. 引用 :在C 中,必须初始化引用(与指针相反)以绑定到某些对象。在没有初始化程序的情况下创建引用是非法的。在C 中,指定此方法的方式是使用初始化程序列表,因为如果要在不首先对其进行初始化的情况下引用构造函数主体中的引用,则将使用未初始化的引用。在Java中,对象引用的行为类似于C ++指针,并且可以在创建后分配给它们。他们只是默认为null其他方式。

  3. 直接子对象 。在C 中,对象可以直接包含对象作为字段,而在Java中,对象只能保存对这些对象的 引用 。也就是说,在C 中,如果html" target="_blank">声明一个具有a string作为成员的对象,则该字符串的存储空间将直接建立在该对象本身的空间中,而在Java中,您仅获得用于引用其他对象的空间String对象存储在其他位置。因此,C ++需要为您提供一种为这些子对象提供初始值的方法,因为否则它们将保持未初始化状态。默认情况下,它对这些类型使用默认构造函数,但是如果您要使用其他构造函数,或者没有默认构造函数可用,则初始化器列表为您提供了一种绕过此方法的方法。在Java中,您不必为此担心,因为引用将默认为null,然后可以将它们分配为引用您实际希望它们引用的对象。如果要使用非默认构造函数,则不需要任何特殊语法。只需将引用设置为通过适当的构造函数初始化的新对象即可。

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

希望这可以帮助!



 类似资料:
  • 如果我有一个struct Foo和一个struct Bar: 如果我初始化一个条并打印正确得到的值: 但是现在如果我声明这样的构造函数: 我失去了Bar::foo的默认构造,程序输出了32764 0 5! 为什么我不得不像这样无声地初始化每个成员变量: 只要我声明一个构造函数?在这种情况下,为什么默认构造不起作用?

  • 为什么x没有在下面初始化? 平均而言,对于一半的迭代,for循环中的将是,从而初始化。对于另一半,找到的 循环替换为 同样糟糕。只有

  • 问题内容: 我有这个代码: 这会导致编译错误:可能尚未初始化,这很公平。 现在,我将代码更改为: 我得到同样的编译错误!我必须初始化为null: 那么,不初始化对象和初始化为null有什么区别?如果我声明一个没有初始化的对象,它是否为null? 谢谢 问题答案: 字段(成员变量)被初始化为(或初始化为默认的原始值,如果它们是原始的) 局部变量未初始化,您有责任设置初始值。

  • 根据此堆栈溢出问题的公认(且唯一)答案, 使用 将改为零初始化对象。 那么,为什么呢?, 生成此输出: 定义的两个构造函数都是默认的?正当对于POD类型,默认初始化为零初始化。 根据这个问题的公认答案, 如果POD成员未在构造函数中初始化,也未在类初始化中通过C11初始化,则默认为已初始化。 不管是堆栈还是堆,答案都是一样的。 在C 98中(而不是之后),new int()被指定为执行零初始化。

  • 问题内容: 我们可以将代码放入构造函数或方法或初始化块中。初始化块有什么用?每个Java程序都必须有它吗? 问题答案: 首先,有两种类型的初始化块: 实例初始化块,以及 静态初始化块。 此代码应说明它们的用法以及执行顺序: 印刷品: 如果要运行某些代码而不管使用哪个构造函数,或者想要对匿名类进行一些实例初始化,则实例迭代块很有用。

  • 问题内容: ava中的Double Brace初始化语法()是什么? 问题答案: 双括号初始化将创建一个从指定类(外部括号)派生的匿名类,并在该类(内部括号)内提供一个初始化程序块。例如 请注意,使用这种双重括号初始化的作用是创建匿名内部类。创建的类具有this指向周围外部类的隐式指针。尽管通常不是问题,但在某些情况下(例如序列化或垃圾收集时)可能会引起悲伤,值得一提的是。