Java 几种方法初始化 Set

本文介绍了Java中Set实例的两种初始化方法,包括使用Set接口的add(E e)方法和利用匿名内部类及实例初始化代码块。通过示例代码详细解释了匿名内部类和实例初始化代码块的概念,并探讨了实例初始化代码块与构造函数的调用顺序。此外,还提供了一个代码示例展示实例初始化代码块在构造函数之前执行。
摘要由CSDN通过智能技术生成

  创建 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 编译器在每个构造函数中会自动复制实例初始化代码块的代码。

文章参考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值