Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/404.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用初始化块的优点是什么?_Java_Initialization - Fatal编程技术网

Java 使用初始化块的优点是什么?

Java 使用初始化块的优点是什么?,java,initialization,Java,Initialization,我知道初始化块在第一次加载类(静态初始化块)或创建实例(实例初始化块)时运行 但当我们可以这样做时,这有什么特别的好处: class SmallInit { static int x = 7; int y = 8; } 没有什么特别的好处,它在某些情况下(通常是在声明多个成员时)有助于可读性。对于只包含一行变量声明的静态块,我看不到任何特别的好处。事实上,当您所做的只是为类或实例变量赋值时,(在我看来)更难理解发生了什么 但是,当需要建立更复杂的起始状态时,静态块和实例块确实很方便

我知道初始化块在第一次加载类(静态初始化块)或创建实例(实例初始化块)时运行

但当我们可以这样做时,这有什么特别的好处:

class SmallInit {
   static int x = 7;
   int y = 8;
}

没有什么特别的好处,它在某些情况下(通常是在声明多个成员时)有助于可读性。

对于只包含一行变量声明的静态块,我看不到任何特别的好处。事实上,当您所做的只是为类或实例变量赋值时,(在我看来)更难理解发生了什么

但是,当需要建立更复杂的起始状态时,静态块和实例块确实很方便。下面是一个同时使用声明和静态块的示例:

static List<Sprocket> mySprockets = new ArrayList<Sprocket>();

static {
    mySprockets.add(new Sprocket("foo", 17));
    mySprockets.add(new Sprocket("bar", 8));
}
静态列表mySprockets=newarraylist(); 静止的{ 添加(新链轮(“foo”,17)); 添加(新链轮(“杆”,8)); }
以下可能是实例初始化块的优点:

Java编译器将初始值设定项块复制到每个构造函数中。因此,这种方法可以用于在多个构造函数之间共享一块代码


好的概述。

我过去使用过初始化块来填充复杂的数据结构。然而,我觉得编写一个填充数据结构的静态函数并调用它是一种更好的方法

e、 g


例如,有些人不熟悉初始化程序块,如果您决定在其他上下文中使用init代码,那么您可以轻松地调用该函数。

实例初始化程序块的一个优点是,它们使模式成为可能

与此相反:

Set<String> names = new HashSet<String>();
names.add("Peter");
names.add("Paul");
names.add("Mary");
  • 如果没有初始值设定项,变量将被初始化 设置为0或null。因此,如果要在 如果将构造函数设置为其他值,则实际上是将其设置两次(一次) 设置为0或null,然后再次在构造函数中设置为所需的值)。这个 在绝大多数情况下,绩效罚款可以忽略不计(A 例外情况可能是在紧密循环中使用的数学类,但 甚至这也将非常依赖于该循环中发生的其他情况)
  • 它有助于提高可读性
  • 如果从构造函数调用虚方法,则派生的 重写的虚拟方法中使用的类的值将为0或null 除非它有初始值设定项。我不是百分之百地相信Java就是这样 已经有一段时间了;我知道它是用C

  • 请参阅和所有答案,但已接受;)@Xaerxess的可能副本:我希望我能接受评论作为答案:)为了我的缘故,下次再问类似的问题:)PS如果你想,你可以发布这个问题的答案,其中包含链接,并解释你在那里找到的最佳答案。注意这一点-它绝对有效,但它会创建一个内部类,其中包含对“this”的隐式引用。如果您没有预料到,这可能会导致一些有趣的GC行为。。。我不是说不要使用它(我当然会),但要注意。@KevinDay你能详细说明一下吗?我对可能出现的潜在问题很感兴趣。当然-如果你像这样初始化一个映射,它会以一个对外部对象的隐式引用结束。如果随后将该映射传递到应用程序的另一个区域,“外部对象”将不会被释放,直到映射本身也被释放。如果映射纯粹是对象的一个实现,那么这很好。但是,如果您在外部接口中公开映射,它会向您打开像这样的意外引用。
    private static Map foo = initFoo();
    
    private static Map initFoo() {
      Map foo = new Map();
      foo.put("x", "y");
      foo.put("a", "b");
      return foo;
    }
    
    Set<String> names = new HashSet<String>();
    names.add("Peter");
    names.add("Paul");
    names.add("Mary");
    
    Set<String> names = new HashSet<String>() {{
        add("Peter");
        add("Paul");
        add("Mary");
    }};
    
    doSomethingToSet(new HashSet<String>() {{
        add("Peter");
        add("Paul");
        add("Mary");
    }});