Java 几种方法初始化 Set

  创建 Set 实例并初始化的方法有多种,举例如下。

一、利用 Set 接口的 add(E e) 方法
	public static void main(String[] args) {
    
    
        Set<Integer> set = new HashSet<>();
        set.add(1);
        set.add(2);
        set.add(3);
        System.out.println(set);  // [1, 2, 3]
    }

  这是很容易想到的方法,也是笔者最常用的方法。

二、利用匿名内部类和实例初始化代码块
	public static void main(String[] args) {
    
    
        Set<Character> set = new HashSet() {
    
      // 这个括号用来创建匿名内部类
            {
    
      // 这个括号表示是匿名内部类的实例初始化块
                add('a');
                add('b');
                add('c');
            }
        };
        System.out.println(set);               // [a, b, c]
        System.out.println(set.contains('a')); // true
    }

  这种初始化方法,比第一种要简单一些,利用的有两个 Java 知识点,一个是匿名内部类,一个是实例初始化代码块。
  所谓匿名内部类也就是没有名字的内部类,一般只使用一次。而匿名内部类的实现方式也就是当创建一个父类对象时,后边加一个大括号,例如:

Set set = new HashSet(){
    
    };

  当定义一个类的时候,一般会定义构造函数,有时候还会定义静态代码块和实例初始化代码块,比如:

package com.example.demo;

public class TestClass {
    
    
	// 构造函数
    TestClass() {
    
    
        System.out.println("I am a constructor");
    }
	// 静态代码块,特点:随着类的加载⽽执⾏,⽽且只执⾏⼀次。
	// 执⾏优先级⾼于⾮静态的初始化代码块,它会在类初始化的时候执⾏⼀次,执⾏完成便销毁,它仅能初始化类变量,即 static 修饰的成员变量。
    static {
    
    
        System.out.println("I am a static method");
    }
	// 实例初始化代码块,本质上是代码块。特点:随着类的加载⽽执⾏,⽽且只执⾏⼀次。
	// 执⾏的时候如果有静态代码块,先执⾏静态代码块再执⾏⾮静态代码块,在每个对象⽣成时都会被执⾏⼀次,它可以初始化类的成员变量。
	// ⾮静态初始化代码块会在构造函数执⾏时,在构造函数主体代码执⾏之前被运⾏。
    {
    
    
        System.out.println("Instance initializer block invoked");
    }

    public static void main(String[] args) {
    
    
        TestClass testClass = new TestClass();
        // 分别输出以下三行
        // I am a static method
        // Instance initializer block invoked
        // I am a constructor
    }
}

  实例初始化代码块用于初始化实例成员,它在每次创建类的实例时运行。
  那么既然之前我们定义了一个匿名内部类,那么它和正常的类一样,也会执行相应的初始化操作(匿名内部类没有构造函数),这也就是我们初始化 Set 时的第二个大括号,这个大括号定义了实例初始化代码块,所以在创建对象的时候就会被执行。

三、探究:实例初始化代码块和构造函数哪个先调用?

  看下方例子。

package com.example.demo;

public class B {
    
    
    B() {
    
    
        System.out.println("constructor");
    }

    {
    
    
        System.out.println("instance initializer block");
    }

    public static void main(String[] args) {
    
    
        B b = new B();
        // 输出如下结果:
        // instance initializer block
        // constructor
    }
}

  上述代码在执行过程中输出结果为:

instance initializer block
constructor

  在上面的例子中,似乎首先调用实例初始化代码块,但是其实不是。 实例初始化代码块在对象创建时被调用。 java 编译器在构造函数中复制实例初始化块。 首先,调用构造函数,执行实例初始化代码块,再执行原构造函数方法。 让我们看下编译后的 B.class 文件来理解它。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.example.demo;

public class B {
    
    
    B() {
    
    
        System.out.println("instance initializer block");
        System.out.println("constructor");
    }

    public static void main(String[] args) {
    
    
        new B();
    }
}

  注意:java 编译器在每个构造函数中会自动复制实例初始化代码块的代码。

文章参考

猜你喜欢

转载自blog.csdn.net/piaoranyuji/article/details/125261678