代码之家  ›  专栏  ›  技术社区  ›  Victor Sorokin

新类(…)…初始化习语[重复]的含义

  •  43
  • Victor Sorokin  · 技术社区  · 15 年前

    这个问题已经有了答案:

    什么? {{ ... }} 以下代码中的块平均值?

    class X {
    
        private Y var1;
    
        private X() {
            Z context = new Z(new SystemThreadPool()) {{
                var1 = new Y();
            }};
        }
    
    }
    
    4 回复  |  直到 9 年前
        1
  •  66
  •   CupawnTae    10 年前

    它叫 double curly brace initialization .(编辑:链接已删除, archived here )

    这意味着您正在创建一个匿名子类,而双括号中的代码基本上是一个构造函数。它通常用于向集合中添加内容,因为Java的语法用于创建本质上的集合常量,这有点尴尬。

    所以你可以这样做:

    List<String> list = new ArrayList<String>() {{
      add("one");
      add("two");
      add("three");
    }};
    

    而不是:

    List<String> list = new ArrayList<String>();
    list.add("one");
    list.add("two");
    list.add("three");
    

    实际上我不喜欢这样,我更喜欢这样做:

    List<String> list = Arrays.asList("one", "two", "three");
    

    因此,在这种情况下,它没有多大意义,但是它确实有地图,比如说,没有一个方便的助手。

        2
  •  11
  •   gustafc    15 年前

    “外部”大括号表示您正在创建匿名子类,第二个大括号是对象初始值设定项。初始值设定项在类的构造函数之前运行,但在任何构造函数之后运行 super 调用(因此也在任何超类初始值设定项之后)。也可以在非匿名类中使用初始值设定项,这是启动 final 如果有几个构造函数不能相互调用,或者字段需要比通常字段初始值设定项允许的更复杂的初始化,则返回字段。

    考虑这个类:

    class X extends Y{
        private final int lulz;
    
        private static boolean someCondition(){...}
        private static boolean danger() throws SomeException { ... }
        public X(A a) throws SomeException {
            super(a); 
            lulz = someCondition()? danger() : 0;
        }
        public X(B b) throws SomeException {
            super(b); 
            lulz = someCondition()? danger() : 0;
        }
    }
    

    它可以改写为:

    class X extends Y{
        private final int lulz;
    
        private static boolean someCondition(){...}
        private static boolean danger() throws SomeException { ... }
        { // initalizer -- might throw SomeException!
            lulz = someCondition()? danger() : 0;
        }
        public X(A a) throws SomeException { super(a); }
        public X(B b) throws SomeException { super(b); }
    }
    

    如果初始值设定项可以引发选中的异常,则所有构造函数都必须声明它们可以引发异常。

        3
  •  4
  •   David Santamaria    15 年前

    您正在创建 anonymous class 并使用 class Instance initialize R成语,如下:

    class X {
        private Y var1;
    
        private X() {
            Z context = new Z(
                   new SystemThreadPool()) {
                       {                        // This is the initialize idiom
                           var1 = new Y();      //
                       }                        //
                   }
              );  // BTW you are missing ")"
        }
    }
    
        4
  •  1
  •   elpddev    11 年前

    如前所述, 双大括号初始化 是正确的。

    它使用一种特定的技术 初始化实例成员 在Java中。这是在类定义中定义的一种简略方法,类定义是一个共享的代码块,当任何类构造函数被激活时,它都将运行。

    我正在将链接添加到 official Java documentations 描述它以获得更广泛的主题观点。

    documentation :

    实例变量的初始值设定项块看起来就像静态的 初始值设定项块,但不包含静态关键字:

    {

    // whatever code is needed for initialization goes here 
    

    }

    Java编译器将初始化器块复制到每个构造函数中。 因此,此方法可用于在 多个构造函数。