栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java“双括号初始化”的效率?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java“双括号初始化”的效率?

这是我对匿名内部类太过迷恋的问题:

2019/05/27  16:35  1,602 DemoApp2$1.class2019/05/27  16:35  1,976 DemoApp2$10.class2019/05/27  16:35  1,919 DemoApp2$11.class2019/05/27  16:35  2,404 DemoApp2$12.class2019/05/27  16:35  1,197 DemoApp2$13.class2019/05/27  16:35  1,953 DemoApp2$30.class2019/05/27  16:35  1,910 DemoApp2$31.class2019/05/27  16:35  2,007 DemoApp2$32.class2019/05/27  16:35    926 DemoApp2$33$1$1.class2019/05/27  16:35  4,104 DemoApp2$33$1.class2019/05/27  16:35  2,849 DemoApp2$33.class2019/05/27  16:35    926 DemoApp2$34$1$1.class2019/05/27  16:35  4,234 DemoApp2$34$1.class2019/05/27  16:35  2,849 DemoApp2$34.class2019/05/27  16:35    614 DemoApp2$40.class2019/05/27  16:35  2,344 DemoApp2$5.class2019/05/27  16:35  1,551 DemoApp2$6.class2019/05/27  16:35  1,604 DemoApp2$7.class2019/05/27  16:35  1,809 DemoApp2$8.class2019/05/27  16:35  2,022 DemoApp2$9.class

这些都是在创建简单应用程序时生成的类,并且使用了大量匿名内部类-每个类都将被编译成一个单独的

class
文件。

如前所述,“双括号初始化”是一个带有实例初始化块的匿名内部类,这意味着将为每个“初始化”创建一个新类,所有这些通常都是为了创建单个对象。

考虑到Java虚拟机在使用它们时将需要读取所有这些类,这可能会导致字节码验证过程中花费一些时间。更不用说增加存储所有这些

class
文件所需的磁盘空间。

利用双括号初始化似乎有一些开销,所以过分地考虑它可能不是一个好主意。但是正如Eddie在评论中指出的那样,不可能绝对确定其影响。

仅供参考,下面是双括号初始化:

List<String> list = new ArrayList<String>() {{    add("Hello");    add("World!");}};

它看起来像Java的“隐藏”功能,但是它只是对以下内容的重写:

List<String> list = new ArrayList<String>() {    // Instance initialization block    {        add("Hello");        add("World!");    }};

因此,它基本上是一个实例初始化块,它是匿名内部类的一部分。

约书亚·布洛赫(Joshua Bloch)为Project Coin设计的Collection Literals提案大致如下:

List<Integer> intList = [1, 2, 3, 4];Set<String> strSet = {"Apple", "Banana", "Cactus"};Map<String, Integer> truthMap = { "answer" : 42 };

可悲的是,它并没有进入Java 7和8中,并被无限期搁置。

实验

下面是简单的实验我已经测试-让1000个

ArrayLists
的元素
"Hello"
,并
"World!"
通过加入到他们
add
的方法,使用两种方法:

方法1:双括号初始化

List<String> l = new ArrayList<String>() {{  add("Hello");  add("World!");}};

方法2:实例化一个ArrayList和add

List<String> l = new ArrayList<String>();l.add("Hello");l.add("World!");

我创建了一个简单的程序来写出Java源文件,以使用以下两种方法执行1000次初始化:

测试1:

class Test1 {  public static void main(String[] s) {    long st = System.currentTimeMillis();    List<String> l0 = new ArrayList<String>() {{      add("Hello");      add("World!");    }};    List<String> l1 = new ArrayList<String>() {{      add("Hello");      add("World!");    }};        List<String> l999 = new ArrayList<String>() {{      add("Hello");      add("World!");    }};    System.out.println(System.currentTimeMillis() - st);  }}

测试2:

class Test2 {  public static void main(String[] s) {    long st = System.currentTimeMillis();    List<String> l0 = new ArrayList<String>();    l0.add("Hello");    l0.add("World!");    List<String> l1 = new ArrayList<String>();    l1.add("Hello");    l1.add("World!");        List<String> l999 = new ArrayList<String>();    l999.add("Hello");    l999.add("World!");    System.out.println(System.currentTimeMillis() - st);  }}

请注意,经过时间初始化1000个

ArrayListS
和1000匿名内部类延伸
ArrayList
使用的检查
System.currentTimeMillis
,所以定时器不具有很高的分辨率。在我的Windows系统上,分辨率大约为15-16毫秒。

两次测试的10次运行的结果如下:

Test1 Times (ms)Test2 Times (ms)--------------------------------187    0203    0203    0188    0188    0187    0203    0188    0188    0203    0

可以看出,双括号初始化的执行时间约为190 ms。

同时,

ArrayList
初始化执行时间为0 ms。当然,应该考虑计时器分辨率,但是很可能在15毫秒以下。

因此,这两种方法的执行时间似乎存在明显差异。看来这两种初始化方法确实存在一些开销。

是的,

.class
编译
Test1
双括号初始化测试程序生成了1000个文件。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/372366.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号