Java中双大括号写法的作用

如何给集合快速初始化呢?可能会用到下面这种写法。

public class Main1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>() {
            {
                add("hello");
                add("world");
            }
        };

        System.out.println(list);

    }

}

一个大括号

一个大括号还是比较好理解的

new Thread(new Runnable() {
            @Override
            public void run() {
                
            }
        }).start();

匿名内部类的一种写法,并不是真正实例化Runnable这个接口。等同于

public class Main1 {

    class TestThread implements Runnable{

        @Override
        public void run() {

        }
    }

    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        new Thread(testThread).start();
    }

}

两个大括号

编译一下下面的代码

public class Main1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>() {
            {
                add("hello");
                add("world");
            }
        };
        System.out.println(list);

    }
}

得到了两个字节码文件

反编译

很明显可以看到,java编译器是如何处理双大括号语法的:

隐式创建了一个类,继承ArrayList,并在这个类的构造方法中,执行双大括号中的代码。

问题

这种写法会带来一种问题,比如我想要初始化多个List

public class Main1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>() {
            {
                add("hello");
                add("world");
            }
        };
        System.out.println(list);
        List<String> list2 = new ArrayList<String>() {
            {
                add("hello");
                add("world");
            }
        };
    }
}

每使用一次这个语法,就会多一个字节码文件,更深层次的问题暂时没遇到,不过最好还是少用吧。

最后跑个题,传统内部类编译后得到如下结果。

public class Main2 {

    class innerClass{
        String year;
        public void hello() {
            say1();
        }
    }

    void say1() {
        System.out.println("1");
    }

    public static void main(String[] args) {
        Main2 main2 = new Main2();

    }
}

可见内部类能访问外部类的方法,是因为把外部类的this通过构造函数传了进来。

参考:

经验分享 程序员 微信小程序 职场和发展