为另一个字符串的子字符串创建一个新字符串是多余的吗?

时间:2014-12-24 06:29:28

标签: java android string

我知道标题不清楚!但是继续阅读,如果你能做出更好的标题,那么就编辑它:)

我有以下几行代码:

    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会抱怨这个并通知我,因为它是多余的?

截图: enter image description here

4 个答案:

答案 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));