【问题标题】:String.substring() making a copy of the underlying char[] value [closed]String.substring() 复制底层 char[] 值 [关闭]
【发布时间】:2016-02-26 21:27:28
【问题描述】:

关于String.substring 的性能注意事项的问题。在 Java 1.7.0_06 之前,String.substring() 方法返回一个新的String 对象,该对象与其父对象共享相同的底层 char 数组,但偏移量和长度不同。当只需要保留一个小的子字符串时,为了避免在内存中保留一个非常大的字符串,程序员曾经编写这样的代码:

s = new String(queryReturningHugeHugeString().substring(0,3));

从 1.7.0_06 开始,没有必要创建新的 String,因为在 Oracle 的 String 实现中,子字符串不再共享其底层 char 数组。

我的问题是:我们是否可以依靠 Oracle(和其他供应商)在未来的某个版本中不返回 char[] 共享,而只需执行 s = s.substr(...),或者我们是否应该显式创建一个新字符串以防万一JRE 的发布又开始使用共享实现了?

【问题讨论】:

  • 不是一个确切的答案,但这里的一个很好的答案stackoverflow.com/a/20275133/2796832 可能会有所帮助。也许如果你真的需要,你可以使用那个答案中的getValueLength,然后用它来标记你的代码。
  • @JonahGraham,不好的建议。这在 Java-9 中可能已经中断:预计 char[] 数组将被替换为 byte[] 。通过反射访问私有 JDK 字段通常不是一个好主意。
  • @TagirValeev TBH 我一直在考虑将该评论作为答案,但这让我感到不舒服。我确信 OP 做了详细的分析,以确保他们代码中的额外复杂性不是过早的优化。但是,我不确定未来的读者是否会给予同样的关注和关注。无论如何,你的答案是一个很好的+1

标签: java string


【解决方案1】:

String 的实际表示是内部实现细节,因此您永远无法确定。然而,根据甲骨文工程师的公开谈话(最著名的是@shipilev),它不太可能被改回来。这样做不仅是为了应对可能的内存泄漏,也是为了简化 String 的内部结构。使用更简单的字符串可以更轻松地实现许多优化技术,例如 String deduplicationCompact Strings

【讨论】:

  • 其实字符串去重的存在也说明了我们无论如何都不需要担心子字符串的表示。如果 JVM 的垃圾收集器能够修补字符串以让相等的实例共享同一个数组,那么假设如果 JVM 供应商决定返回共享子字符串,它也能够修补子字符串并不太牵强(偏移量+长度)表示。
猜你喜欢
  • 2019-11-15
  • 2014-08-13
  • 2018-08-19
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2018-01-31
  • 2017-09-21
  • 2017-09-29
相关资源
最近更新 更多