字符串类的subString()函数如何工作

请参阅以下代码。

String s = "Monday"; if(s.subString(0,3).equals("Mon"){} String s2 = new String(s.subString(0,3)); String s3 = s.subString(0,3); 

我知道第2行仍将指向“星期一”,并且有一个新的String对象,其偏移量和计数设置为0,3。

第4行将在字符串池中创建一个新的字符串“Mon”并指向它。

但不确定第5行是否会表现为第2行或第4行。

如果我错误的第2或第4行也请更正..谢谢

我知道第2行仍将指向“星期一”,并且有一个新的String对象,其偏移量和计数设置为0,3。

目前,Sun JRE的实施也是如此。 我似乎记得过去的Sun实现并不是这样,并且JVM的其他实现也不是这样。 不要依赖未指定的行为。 GNU类路径可能会复制数组(我不记得手头用什么比率来决定何时复制,但是如果副本是原始的一小部分就会复制,这会使一个很好的O(N)算法变为O(N ^ 2))。

第4行将在字符串池中创建一个新的字符串“Mon”并指向它。

不,它在堆中创建一个新的字符串对象,受到与任何其他对象相同的垃圾收集规则的约束。 它是否共享相同的底层字符数组是依赖于实现的。 不要依赖未指定的行为。

String(String)构造函数说:

初始化一个新创建的String对象,使其表示与参数相同的字符序列 ; 换句话说,新创建的字符串是参数字符串的副本。

String(char[])构造函数说:

分配一个新的String,使其表示当前包含在字符数组参数中的字符序列。 复制字符数组内容 ; 后续修改字符数组不会影响新创建的字符串。

遵循良好的OO原则,没有String方法实际上要求它使用字符数组实现,因此String的规范的任何部分都不需要对字符数组进行操作。 将数组作为输入的那些操作指定将数组的内容复制到String中使用的任何内部存储。 字符串可以在内部使用UTF-8或LZ压缩并符合API。

但是,如果您的JVM没有进行小比例子字符串优化,那么当您使用new String(String)时,它有可能只复制相关部分,所以它是一个尝试它的情况,如果它改善内存使用。 并非所有影响Java运行时的东西都是由Java定义的。

要获取字符串池中equal字符串的字符串,请使用intern()方法。 这将从池中检索一个字符串,如果已经实现了该值,或者创建一个新字符串并将其放入池中。 请注意,池化的字符串具有不同的(再次依赖于实现)垃圾回收行为。

正如Pete Kirkham所指出的,这是具体的实施。 我的回答仅适用于Sun JRE,并且仅在Java 7更新6之前。

你正常的substring调用只是创建一个新的字符串,引用与原始字符串相同的字符数组。 这也是第5行发生的事情。 新字符串对象引用恰好分配给变量的事实不会改变方法的行为。

为了清楚起见,你说在第2行,新字符串仍将指向“星期一” – 字符串中的字符串数组引用将与用于“星期一”的字符串相同。 但“星期一”本身就是一个字符串,而不是字符数组。 换句话说,通过时间线2完成(并忽略GC),有两个字符串对象,两者都引用相同的char数组。 一个计数为6,另一个计数为3; 两者都有0的偏移量。

你对使用“字符串池”的第4行错了 – 那里没有汇集。 但是,它与其他线路不同。 当您调用String(String)构造函数时,新字符串会获取原始字符数据的副本 ,因此它是完全独立的。 如果您只需要一个包含非常大的原始字符串的一小部分的字符串,这将非常有用; 当你抓住小部分的副本时,它允许原始的大字符数组被垃圾收集(假设没有别的东西需要它)。 根据我自己的经验,这方面的一个很好的例子就是从一条线上读取线条。 默认情况下, BufferedLineReader将使用80个字符的缓冲区读取行,因此返回的每个字符串将使用至少80个字符的char数组。 如果你正在阅读很多非常短的行(单个单词),只需通过使用奇怪的内容就可以减少内存消耗

 line = new String(line); 

可能非常重要。

这有帮助吗?

注意 :从Sun / Oracle Java中的Java 7更新6开始,String.substring创建的String不再共享父级的char数组。 决定这种优化很少有益,并且没有certificateoffsetcount字段的成本和复杂性。

一些链接:

  • 理由: http : //mail.openjdk.java.net/pipermail/core-libs-dev/2012-May/010257.html
  • 正式的错误报告: http : //bugs.sun.com/bugdatabase/view_bug.do?video_id = 6924259
  • String.java diff: http ://hg.openjdk.java.net/jdk7u/jdk7u/jdk/diff/e1c679a00712/src/share/classes/java/lang/String.java

在第5行—-> s3 =星期一。

在Sun的实现中,String对象具有private final char value[]字段。 通过调用substring()创建新String时,不会创建新的char数组,新实例将使用原始对象的value 。 第2行和第5行就是这种情况,新的String对象将使用s的char数组。

如果字符串长度小于char数组value的总长度,则构造函数String(String)将创建一个新的char数组。 因此第4行中创建的String将使用新的char数组。

你应该看一下构造函数public String(String original)的源代码 ,它非常简单。

阅读http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html

“返回一个新字符串…”