什么是Java中的Double Brace初始化?

Java中的双括号初始化语法( {{ ... }} )是什么?


双括号初始化创建一个从指定类(外括号)派生的匿名类,并在该类内提供一个初始化块(内括号)。 例如

new ArrayList<Integer>() {{
   add(1);
   add(2);
}};

请注意,使用此大括号初始化的效果是您正在创建匿名内部类。 所创建的类有一个隐含的this指针到周围外部类。 虽然通常不是问题,但在某些情况下,例如在序列化或垃圾收集时,可能会导致悲伤,值得注意。


每次有人使用双括号初始化,一只小猫被杀死。

除了语法相当不寻常,并且不是真正的习惯(当然,味道是有争议的),您在您的应用程序中不必要地创建了两个重要问题,我刚刚在此处更详细地介绍了这些问题。

你正在创造太多的匿名课程

每次使用双括号初始化时,都会创建一个新类。 例如这个例子:

Map source = new HashMap(){{
    put("firstName", "John");
    put("lastName", "Smith");
    put("organizations", new HashMap(){{
        put("0", new HashMap(){{
            put("id", "1234");
        }});
        put("abc", new HashMap(){{
            put("id", "5678");
        }});
    }});
}};

...会产生这些类:

Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class

这对于你的类加载器来说是相当大的开销 - 没有任何东西! 当然,如果你做一次,它不会花费太多的初始化时间。 但是,如果你在整个企业应用程序中这样做了20,000次......所有这些只是为了一点“语法糖”而堆起内存?

2.你可能会造成内存泄漏!

如果您采用上述代码并从方法返回该映射,那么该方法的调用者可能会毫无防备地挟持无法收集的非常繁重的资源。 考虑下面的例子:

public class ReallyHeavyObject {

    // Just to illustrate...
    private int[] tonsOfValues;
    private Resource[] tonsOfResources;

    // This method almost does nothing
    public Map quickHarmlessMethod() {
        Map source = new HashMap(){{
            put("firstName", "John");
            put("lastName", "Smith");
            put("organizations", new HashMap(){{
                put("0", new HashMap(){{
                    put("id", "1234");
                }});
                put("abc", new HashMap(){{
                    put("id", "5678");
                }});
            }});
        }};

        return source;
    }
}

返回的Map现在将包含对ReallyHeavyObject的封闭实例的ReallyHeavyObject 。 你可能不想冒这个风险:

来自http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/的图片

你可以假装Java有地图文字

为了回答你的实际问题,人们一直在使用这种语法来假装Java有类似于地图文字的东西,类似于现有的数组文字:

String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};

有些人可能会发现这种句法刺激。


  • 第一个大括号创建一个新的匿名内部类。
  • 第二组大括号在Class中创建一个实例初始化器,如静态块。
  • 例如:

       public class TestHashMap {
        public static void main(String[] args) {
            HashMap<String,String> map = new HashMap<String,String>(){
            {
                put("1", "ONE");
            }{
                put("2", "TWO");
            }{
                put("3", "THREE");
            }
            };
            Set<String> keySet = map.keySet();
            for (String string : keySet) {
                System.out.println(string+" ->"+map.get(string));
            }
        }
    
    }
    

    怎么运行的

    第一个大括号创建一个新的匿名内部类。 这些内部类能够访问其父类的行为。 所以,在我们的例子中,我们实际上是创建了HashSet类的一个子类,所以这个内部类可以使用add()方法。

    第二组大括号只是实例初始值设定项。 如果您提醒核心Java概念,那么您可以轻松地将实例初始化程序块与静态初始化程序相关联,这是由于类似的大括号struct。 唯一不同的是静态初始化器添加了static关键字,并且只运行一次; 不管你创建了多少个对象。

    更多

    链接地址: http://www.djcxy.com/p/82397.html

    上一篇: What is Double Brace initialization in Java?

    下一篇: How do I join two lists in Java?