我们创建并初始化一个对象,往往有多种方法,多少人知道 {} 也是一种?这种方法独特,是不是一个良好的特性呢?

# 普通初始化

通常我们会这样创建对象并初始化,如下创建一个 List

List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list);

主要分为两部分:1. 创建对象 2. 初始化数据


# 双大括号法

利用这种方法,我们可以把创建和初始化写在一起

List<Integer> list = new ArrayList<>()<!--swig0-->;
        System.out.println(list);

# 好处与坏处

好处

  1. 相对普通的看起来行数更少 (不考虑换行等)
  2. 可读性更高
  3. 创建和初始化在同一个表达式里完成了

坏处

  1. 并不是一个被广泛知道和使用的方法
  2. 每次使用它都会额外产生一个匿名类

第一层括号:实际是定义了一个匿名内部类 (Anonymous inner Class)

第二层括号:实际上是一个实例化初始化块 (Instance initializer block) 这个块在内部匿名类构造时被执行,这个块之所以被叫做 "实例化初始化块" 是因为它们被定义了一个类的实力范围内

解析原因

在 cmd 中,进行编译

javac TestHashMap.java

生成两个类

image_2022-12-27-10-31-20

正如,双括号写法的原理一样,生成一个 Niubi666.class (外部实体类), 及 Niubi666$1.class (内部匿名类)

Niubi666.class (外部实体类)

public class Niubi666 {
    static Map<Character,Integer> map = new HashMap<Character,Integer>()<!--swig1-->;
    public static void main(String[]args){
        System.out.println(map);
        System.out.println("Hello,java");
    }
}

Niubi666$1.class (内部匿名类)

public class Niubi666 {
    public static void main(String[]args){
        Map<Character,Integer> map = new HashMap<>();
        map.put('I',1);
        System.out.println(map);
    }
}
  1. 不支持泛型推断 (List<String> list = new ArrayList<>())(也就是后面必须加泛型)
  2. 不支持 final 的类
  3. 会持有隐式的引用,这可能会导致内存泄露

其它更好的选择

使用 Stream 的工厂方法

list = Stream.of("Linux", "Windows", "Mac")
        .collect(Collectors.toList());
assertTrue(list.contains("Windows"));

java9 可以使用 Collections 的工厂方法

List<String> list = List.of("Linux", "Wiondows", "Mac");
Set<String> set = Set.of("Linux", "Wiondows", "Mac");