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双大括号初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBoot+vue+Axios实现Token令牌的详细过程
Token是在服务端产生的,前端可以使用用户名/密码向服务端请求认证(登录),服务端认证成功,服务端会返回 Token 给前端,Token可以使用自己的算法自定义,本文给大家介绍SpringBoot+vue+Axios实现Token令牌,感兴趣的朋友一起看看吧2023-10-10
SpringBoot详解整合MyBatis过程中可能遇到的问题
因为Spring Boot框架开发的便利性,所以实现Spring Boot与数据访问层框架(例如MyBatis)的整合非常简单,主要是引入对应的依赖启动器,并进行数据库相关参数设置即可2022-07-07
Java8新特性之lambda的作用_动力节点Java学院整理
我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值。现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作解开lambda最强作用的神秘面纱。2017-06-06
Java中的System类、BigInteger类和BigDecimal类详解
这篇文章主要介绍了Java中的System类、BigInteger类和BigDecimal类详解,arraycopy()方法,复制数组元素,比较适合底层调用,一般使用Arrays.copyOf()完成复制数组,需要的朋友可以参考下2023-09-09


最新评论