实例初始化器与构造函数有何不同?

Aja*_*jay 71 java instantiation

换句话说,为什么需要实例初始化器?在构造函数上编写实例初始化程序有什么区别或优势?

jav*_*y79 100

这似乎解释得很好:

在以下情况下,实例初始值设定项是实例变量初始化程序的有用替代

  • 初始化代码必须捕获异常,或

  • 执行无法用实例变量初始化程序表示的花哨计算.当然,您可以在构造函数中编写此类代码.

但是在具有多个构造函数的类中,您必须在每个构造函数中重复代码.使用实例初始化程序,您只需编写一次代码,无论使用何种构造函数创建对象,都将执行该代码.实例初始值设定项在匿名内部类中也很有用,它们根本不能声明任何构造函数.

来自:爪哇 JavaWorld 对象初始化.

  • 另一方面,您可以在一个构造函数中编写一次代码,然后从所有其他构造函数中调用它.但匿名的内部课程是一个很好的观点. (16认同)
  • 你可以从其他构造函数中调用它 - 但是你再次重复调用.如果添加新构造函数,则必须记住添加对它的调用.实例初始化器不是这样. (11认同)
  • @talonx,我同意你关于遗忘的论点,但利用默认行为同样危险.当支持者通过遗留代码中的构造函数进行读取时,人们不会总是记得检查可能的实例初始化器.而明确使用的init()将脱颖而出. (5认同)
  • @Assambar您不能在init()方法中指定最终字段,但可以在初始化程序块中指定. (4认同)

yka*_*ich 20

就对象生命周期而言,没有区别.两者都在构造时调用,逻辑上初始化块可以被视为构造的一部分.

从语义上讲,初始化程序是一个很好的工具,有以下几个原因:

初始化程序可以通过将初始化逻辑保持在初始化变量旁边来提高代码可读性:

   public class Universe {
       public int theAnswer;
       {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;
       }

       // a bunch of other vars
   }
Run Code Online (Sandbox Code Playgroud)

VS

   public class Universe {
       public int theAnswer;

       // a bunch of other vars

       public Universe() {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;

         // other constructor logic
       }
   }
Run Code Online (Sandbox Code Playgroud)

无论使用哪个构造函数,都会调用初始化程序.

初始化程序可以在匿名内部类中使用,而构造函数则不能.

  • 你拥有它们在技术上是一个"实例变量初始化器"而不是"实例初始化器"(一个直接嵌套在一个类中的块).参见JLS第3节8.6. (3认同)

Rah*_*arg 8

当你有许多构造函数并希望为每个构造函数执行一些公共代码时,可以使用实例初始化器.因为它是为所有构造函数调用的.