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

如果使用字符串常量,我们的行为是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提供相同的行为。


一只斗牛犬
浏览 519回答 2
2回答

四季花海

首先,String(String)“复制”构造函数源于最初的日子并且是异常的。也许是因为String.intern()其中有一些复制预防,以及常量"..."。它永远不需要,因为String是一个不可变final类。因为Integer有Integer.valueOf(int)使用瞬时的缓存,默认情况下保持-128到127。尽管涉及非常称职的编译器开发团队,但java字节码编译器编译非常幼稚。但是,在机器代码的字节代码上,可能会发生一些不错的事情。例如,对象不是在堆上创建的,而是在堆栈上创建的。简单编译至少不太可能在智能技巧的数据流分析中包含错误。(这也是提供良好代码风格的好理由。)一个例子:List<String>&nbsp;list&nbsp;=&nbsp;...String[]&nbsp;array1&nbsp;=&nbsp;list.toArray(new&nbsp;String[0]);String[]&nbsp;array2&nbsp;=&nbsp;list.toArray(new&nbsp;String[list.size()]);toArray需要一个实际的数组实例,因为类型擦除List list不再知道它包含Strings。历史上,作为优化,可以传递适合大小的数组(这里是版本list.size()),然后返回。更优化和更快,仍然有一些风格检查标记第一个版本。然而实际上第一个版本更快,因为使用了另一个数组字节cdoe实例化,并且array1将更快地生成。关于某些数字划分的相同故事。在C中,有许多编译器优化涉及更快的移位。这是(部分)在Java中以字节代码完成的,用于机器代码编译,这是这些优化的更合理的地方。我个人认为优化字节码编译器会很好,也许适合大学项目。但是,对于代码改进而言,可能不合理,例如不使用.equals枚举值。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java