为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在java中,当最终结果是interned对象的不可变副本时,编译器不会优化new?

为什么在java中,当最终结果是interned对象的不可变副本时,编译器不会优化new?

一只斗牛犬 2019-04-25 18:15:04
如果使用字符串常量,我们的行为是Java编译器将使用相同的实例  String a = "abc";   String b = "abc";   //a == b   String c = new String("abc");   // c is a brand new object on the heap;为什么java编译器不优化新的String并用等效赋值替换它?是否有一些深层次的设计决定,或者只是巧合?我们是否可以期望不同的JVM或编译器更具攻击性,并且实际上用一个众所周知的静态对象替换不可变对象的堆实例?虽然String是最臭名昭着的例子,但我们可以为Integer提供相同的行为。
查看完整描述

2 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

首先,String(String)“复制”构造函数源于最初的日子并且是异常的。也许是因为String.intern()其中有一些复制预防,以及常量"..."。它永远不需要,因为String是一个不可变final类。

因为IntegerInteger.valueOf(int)使用瞬时的缓存,默认情况下保持-128到127。

尽管涉及非常称职的编译器开发团队,但java字节码编译器编译非常幼稚。但是,在机器代码的字节代码上,可能会发生一些不错的事情。例如,对象不是在堆上创建的,而是在堆栈上创建的。

简单编译至少不太可能在智能技巧的数据流分析中包含错误。(这也是提供良好代码风格的好理由。)

一个例子:

List<String> list = ...String[] array1 = list.toArray(new String[0]);String[] array2 = list.toArray(new String[list.size()]);

toArray需要一个实际的数组实例,因为类型擦除List list不再知道它包含Strings。

历史上,作为优化,可以传递适合大小的数组(这里是版本list.size()),然后返回。更优化和更快,仍然有一些风格检查标记第一个版本。然而实际上第一个版本更快,因为使用了另一个数组字节cdoe实例化,并且array1将更快地生成。

关于某些数字划分的相同故事。在C中,有许多编译器优化涉及更快的移位。这是(部分)在Java中以字节代码完成的,用于机器代码编译,这是这些优化的更合理的地方。

我个人认为优化字节码编译器会很好,也许适合大学项目。但是,对于代码改进而言,可能不合理,例如不使用.equals枚举值。


查看完整回答
反对 回复 2019-05-15
  • 2 回答
  • 0 关注
  • 518 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号