Java中双大括号初始化的理解与使用

 更新时间:2022年06月20日 11:27:50   作者:不如一默  
最近重读Java 编程思想,读到有关实例化代码块儿的内容,使我对于使用两个大括号进行初始化有了更深的理解,下面这篇文章主要给大家介绍了关于Java中双大括号初始化的理解与使用的相关资料,需要的朋友可以参考下

偶然机会看到一种对象初始的方式:

    // 新建一个列表,并赋值 "Harry","Tony","Tom"
    ArrayList<String> friends = new ArrayList<String>() {{
        add("Harry");
        add("Tony");
        add("Tom");
    }};

当然,对Map集合也用同种初始化方式:

    // 新建一个Map,并赋值
    Map<String, Object> cat = new HashMap<String, Object>() {{
        put("name", "Tom");
        put("age", 10);
    }};

这里利用了内部类语法,这种方式比先new出对象然后再进行依次add要方便、简洁许多。该方法称之为“双括号初始化”(double brace initialization)。

对该方法的理解

以ArrayList的初始化为例,第一层花括号,首先对定义了一个继承自ArrayList的匿名内部类

    ArrayList<String> friends = new ArrayList<String>() {
        // 这里什么操作都没有,全部继承自父类(ArrayList)
    };

第二层则是一个自定义的对象构造块(称之为 非静态初始化块)

    new ArrayList<String>() {
        // 这里什么操作都没有,全部继承自父类(ArrayList)
    };

我们通过new得到ArrayList的子类的实例化,然后上转型为ArrayList的引用

    ArrayList<String> friends = new ArrayList<String>() {{}};
  • 我们得到的 friends 实际上是ArrayList的子类的引用,但在功能上没有任何改变
  • 相比于常规标准方式进行初始化要简洁许多(但代码可读性相对会差)

效率问题

利用双大括号初始化集合从效率上来说可能不如标准的集合初始化步骤。原因在于使用双大括号初始化会导致内部类文件的产生,而这个过程就会影响代码的执行效率。

首先查看不同初始化方式生成的.class文件

例如以下代码:

public class Test1 {

    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());
        ArrayList<String> list1 = new ArrayList<String>() {{
            add("Harry");
            add("Tony");
            add("Tom");
            add("Jerry");
        }};

        ArrayList<String> list2 = new ArrayList<String>() {{
            add("Harry");
            add("Tony");
            add("Tom");
            add("Jerry");
        }};

        ArrayList<String> list3 = new ArrayList<String>() {{
            add("Harry");
            add("Tony");
            add("Tom");
            add("Jerry");
        }};

        ArrayList<String> list4 = new ArrayList<String>() {{
            add("Harry");
            add("Tony");
            add("Tom");
            add("Jerry");
        }};

        ArrayList<String> list5 = new ArrayList<String>() {{
            add("Harry");
            add("Tony");
            add("Tom");
            add("Jerry");
        }};
		
		……
		…snip…
		……
		
		ArrayList<String> list1000 = new ArrayList<String>() {{
            add("Harry");
            add("Tony");
            add("Tom");
            add("Jerry");
        }};
        
        System.out.println(System.currentTimeMillis());
    }
}

Test1编译后生成的.class列表为:

Test1$1.class
Test1$2.class
Test1$3.class
Test1$4.class
Test1$5.class
……
…snip…
……
Test1$1000.class
Test1.class

生成了 1001个.class文件

public class Test2 {

    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());

        ArrayList<String> list1 = new ArrayList<>();
        list1.add("Harry");
        list1.add("Tony");
        list1.add("Tom");
        list1.add("Jerry");

        ArrayList<String> list2 = new ArrayList<>();
        list2.add("Harry");
        list2.add("Tony");
        list2.add("Tom");
        list2.add("Jerry");

        ArrayList<String> list3 = new ArrayList<>();
        list3.add("Harry");
        list3.add("Tony");
        list3.add("Tom");
        list3.add("Jerry");

        ArrayList<String> list4 = new ArrayList<>();
        list4.add("Harry");
        list4.add("Tony");
        list4.add("Tom");
        list4.add("Jerry");

        ArrayList<String> list5 = new ArrayList<>();
        list5.add("Harry");
        list5.add("Tony");
        list5.add("Tom");
        list5.add("Jerry");
		
		……	
		…snip…
		……
		
		ArrayList<String> list1000 = new ArrayList<>();
        list1000.add("Harry");
        list1000.add("Tony");
        list1000.add("Tom");
        list1000.add("Jerry");

        System.out.println(System.currentTimeMillis());
    }
}

Test2编译后生成的.class列表为:

Test2.class

只生成了1个.class文件

运行时间

第一段代码Test1运行结果:

1508379452224
1508379452784

运行时间为:560毫秒

第二段代码Test2运行结果:

1508379671505
1508379671507

运行时间为:2毫秒

虽然说这个时间差距会根据电脑性能以及运行状态有所变化,但也能说明双大括号初始化方法要比常规方法用时长

综上,(测试初始化数据较少(list未达到自增临界点)的情况下)双大括号初始化方法要比常规方法效率低:

1. 双大括号初始化方法生成的.class文件要比常规方法多

2. 双大括号初始化方法运行时间要比常规方法长

总结

到此这篇关于Java中双大括号初始化的理解与使用的文章就介绍到这了,更多相关Java双大括号初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Java ASM使用logback日志级别动态切换方案展示

    Java ASM使用logback日志级别动态切换方案展示

    这篇文章主要介绍了Java ASM使用logback日志级别动态切换方案展示,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Intellij IDEA 录制快捷键实现自动格式化的方法

    Intellij IDEA 录制快捷键实现自动格式化的方法

    这篇文章主要介绍了Intellij IDEA 录制快捷键实现自动格式化的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot Admin 如何实现Actuator端点可视化监控

    SpringBoot Admin 如何实现Actuator端点可视化监控

    这篇文章主要介绍了SpringBoot Admin 如何实现Actuator端点可视化监控,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 一文带你搞懂Redis分布式锁

    一文带你搞懂Redis分布式锁

    本篇文章主要来介绍一下如何Redis实现分布式锁的演进过程,以及为什么不能直接用Setnx实现分布式锁,文中的示例代码讲解详细,需要的可以参考一下
    2022-09-09
  • RxJava中多种场景的实现总结

    RxJava中多种场景的实现总结

    这篇文章给大家详细介绍了RxJava中多种场景的实现,对大家学习使用RxJava具有一定的参考借鉴价值,有需要的朋友们可以参考学习,下面来一起看看吧。
    2016-10-10
  • 如何在java中正确使用注释

    如何在java中正确使用注释

    在编写程序时,经常需要添加一些注释,用以描述某段代码的作用。 一般来说,对于一份规范的程序源代码而言,注释应该占到源代码的 1/3 以上。下面我们来详细了解一下吧
    2019-06-06
  • 解决spring boot网关gateway导致的坑,无法下载文件问题

    解决spring boot网关gateway导致的坑,无法下载文件问题

    这篇文章主要介绍了解决spring boot网关gateway导致的坑,无法下载文件的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java反射原理制作对象打印工具

    java反射原理制作对象打印工具

    本文主要给大家介绍了java反射原理制作对象打印工具的方法和代码,以及一个热心网友给出的更加简洁方便的代码,小伙伴们需要的话可以参考下。
    2015-12-12
  • idea 创建properties配置文件的步骤

    idea 创建properties配置文件的步骤

    这篇文章主要介绍了idea 创建properties配置文件的步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Springboot+QueryDsl实现融合数据查询

    Springboot+QueryDsl实现融合数据查询

    这篇文章主要将介绍的是 Springboot 使用 QueryDsl 实现融合数据查询,文中有详细的代码讲解,对 SpringBoot Querydsl 查询操作感兴趣的朋友一起看看吧
    2023-08-08

最新评论