我知道标题不清楚!但是继续阅读,如果你能做出更好的标题,那么就编辑它:)
我有以下几行代码:
List<Headline> headlines = new ArrayList<>();
String openingTag = "<NEWS>";
String closingTag = "</NEWS>";
while(xml.contains(openingTag) && xml.contains(closingTag)) {
String partialXml;
partialXml = new String(xml.substring(xml.indexOf(openingTag), xml.indexOf(closingTag) + closingTag.length()));
// Remove what I have stored in another variable using substring. But
// substring uses the same backing array as xml, so is it going to be
// removed from my other variable?
xml = xml.replace(partialXml, "");
headlines.add(makeHeadline(partialXml));
}
在Java String.substring(int, int)
的Android文档中:
The returned string shares this string's backing array
根据我的理解,如果我要更改xml
变量,我必须使用String.substring(int, int)
new String(xml.substring(int, int))
的结果存储在变量中
我对这个结论是对的吗?
如果我是对的,那么为什么Android Studio会抱怨这个并通知我,因为它是多余的?
截图:
答案 0 :(得分:7)
Java中的一个字符串最初由一个支持的字符数组和一个start/length
指示(或者它可能是start/end
组成,我无法记住 - 足以说它有足够的信息来在进行子串时,在后备存储中使用相同的实际字符数组。)
这允许字符串(不可变)共享相同的数据,例如:
str1 = new String("Pax is great");
str2 = str1.substring(0,3);
在记忆中,这看起来像是:
str1 (backing, 0, 12)
str2 (backing, 0, 3)
+------------+
backing = |Pax is great| (shared)
+------------+
因此,从子字符串操作(它本身就是一个新字符串)创建一个 new 字符串确实是多余的,如前面的图表所示(除了一种情况,见下文)。
如果修改其中一个字符串str2 = new String("xyzzy")
,或任何其他操作意味着它不能再使用相同的字符,那么它将获得 new 自动支持值。
我相信这在JVM的后续版本中发生了变化(1.7.0_06,寻找错误ID 6924259)。这是我前面提到的情况,原始行为可能会导致你分配一个大字符串的麻烦,占用它的一个小子串,然后摆脱原来的。
在这种情况下, small 字符串将保留大支持数组,尽管它并不需要它。
这就是new String(str.substring(...))
&#34;技巧&#34;因为它在使用原始方法时为新字符串创建了一个 new 支持数组(较小的一个)。
通过删除共享所做的更改,substring()
现在生成一个新的后备阵列,无论如何。因此,不再需要new String(str.substring(...))
技巧。
答案 1 :(得分:5)
使用接受另一个String作为参数的String的构造函数总是多余的,因为String是不可变的,因此创建一个等于原始实例的新String实例没有意义。
答案 2 :(得分:3)
Java String
是不可变的,创建new String
会污染intern
缓存,但不会完成任何操作。 多余。
答案 3 :(得分:1)
在java中String是不可变的,这意味着任何字符串操作都会导致字符串被转换为新的字符串对象。
当你写这一行时,
String openingTag = "<NEWS>";
在这一行java编译器有字符串文字(在运行时字符串文字被转换为对象),它有共同的字符串池。
这是字符串池在对象内存中以某种方式表示,
+-----------+
| "<NEWS>" |<---- openingTag
+-----------+
现在我们的&#34;新闻&#34;是字符串对象。所以,如果你写一些说明的话,
String subStr1 = openingTag.substring(0,2); // which returns <N
String str1 = new String("<NEWS>");
上面的第一行返回其自身的品牌字符串,它是一个对象对象。 之后
//this is a String pool,
+------------------------------------------------------------------------+
| +-----------+ +------+ |
| str1------>| "<NEWS>" |<---- openingTag | "<N" |<--- subStr1 |
| +-----------+ +------+ |
+------------------------------------------------------------------------+
你写过这样的东西,
其中说子串给你一个字符串,它自己就是一个对象,然后你再次传递该字符串对象作为参数转换成String对象。这是多余的。
String subStr1 = new String(openingTag.substring(0,2));