创建 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 编译器在每个构造函数中会自动复制实例初始化代码块的代码。
文章参考
- java中set的初始化_关于Java Set的初始化方法
- Java实例初始化程序块
相关文章
暂无评论...