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

作者:不如一默 时间:2023-08-30 08:44:55 

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

// 新建一个列表,并赋值 "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要方便、简洁许多。该方法称之为&ldquo;双括号初始化&rdquo;(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
&hellip;&hellip;
&hellip;snip&hellip;
&hellip;&hellip;
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. 双大括号初始化方法运行时间要比常规方法长

来源:https://blog.csdn.net/xukun5137/article/details/78275201

标签:java,双大括号,初始化
0
投稿

猜你喜欢

  • 详解Java token主流框架之JWT

    2022-03-30 19:30:34
  • Android游戏开发学习①弹跳小球实现方法

    2022-04-27 02:48:14
  • Android自定义View实现选座功能

    2022-12-23 00:05:45
  • Java实现用户管理系统

    2023-08-26 17:18:21
  • C#实现向函数传递不定参数的方法

    2021-06-21 01:33:22
  • Django之多对多查询与操作方法详解

    2021-08-03 03:21:58
  • c#可以创建任意控件的拖动方法

    2021-11-30 01:51:08
  • 浅谈Mybatis分页插件,自定义分页的坑

    2021-12-15 01:28:20
  • Android中TextView显示插入的图片实现方法

    2023-08-06 00:27:42
  • C#全局热键设置与窗体热键设置实例

    2022-09-30 05:38:52
  • MyBatis之自查询使用递归实现 N级联动效果(两种实现方式)

    2023-04-15 03:34:50
  • java中常见的死锁以及解决方法代码

    2023-04-07 19:47:30
  • spring boot 2.x html中引用css和js失效问题及解决方法

    2021-08-13 10:28:32
  • Android中webview与JS交互、互调方法实例详解

    2023-04-30 19:18:27
  • Java 定时器的多种实现方式

    2021-06-14 03:15:09
  • 关于多线程常用方法以及对锁的控制(详解)

    2022-02-02 08:16:42
  • java基础(System.err和System.out)详解

    2022-10-23 23:27:37
  • Java基础之容器Vector详解

    2023-11-25 13:10:07
  • java集合与数组的相同点和不同点

    2022-07-19 03:13:53
  • 用C#实现启动另一程序的方法实例

    2023-06-20 12:05:43
  • asp之家 软件编程 m.aspxhome.com