Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 字符串是不可变的-这意味着我永远不应该使用+;=只有StringBuffer?_Java_String_Immutability_Stringbuilder_Stringbuffer - Fatal编程技术网

Java 字符串是不可变的-这意味着我永远不应该使用+;=只有StringBuffer?

Java 字符串是不可变的-这意味着我永远不应该使用+;=只有StringBuffer?,java,string,immutability,stringbuilder,stringbuffer,Java,String,Immutability,Stringbuilder,Stringbuffer,字符串是不可变的,这意味着,一旦创建了字符串,就不能对其进行更改 那么,这是否意味着如果使用+=附加内容,会比创建一个StringBuffer并向其附加文本需要更多内存 如果你使用+=,你每次都会创建一个新的“对象”,它必须保存在内存中,不是吗 是的。字符串是不可变的。对于偶尔使用,+=是可以的。如果+=操作是密集型的,您应该求助于StringBuilder。我认为它依赖GC来收集包含废弃字符串的内存。 因此,如果您对字符串操作有很多操作,那么使用字符串生成器执行+=肯定会更快。但在大多数情况下

字符串是不可变的,这意味着,一旦创建了字符串,就不能对其进行更改

那么,这是否意味着如果使用+=附加内容,会比创建一个StringBuffer并向其附加文本需要更多内存


如果你使用+=,你每次都会创建一个新的“对象”,它必须保存在内存中,不是吗

是的。字符串是不可变的。对于偶尔使用,+=是可以的。如果+=操作是密集型的,您应该求助于StringBuilder。

我认为它依赖GC来收集包含废弃字符串的内存。
因此,如果您对字符串操作有很多操作,那么使用字符串生成器执行+=肯定会更快。但在大多数情况下,这应该不是问题。

没错。如果线程安全不是问题,那么应该使用StringBuilder

作为旁注:可能有几个字符串对象使用相同的backing char[]——例如,每当使用substring(),都不会创建新的char[],这使得使用它非常有效

此外,编译器可能会为您进行一些优化。例如,如果你这样做

static final String FOO = "foo";
static final String BAR = "bar"; 

String getFoobar() {
  return FOO + BAR; // no string concatenation at runtime
}

如果编译器在可能的情况下在内部使用StringBuilder来优化字符串连接,我也不会感到惊讶,如果将来还没有的话。

是的,你会这样做,这就是为什么你应该使用StringBuffer来连接很多字符串


还要注意的是,由于Java5,大多数时候您也应该更喜欢StringBuilder。它只是某种不同步的StringBuffer。

但是垃圾收集器将在Java 5或更高版本中没有对旧字符串的引用时释放这些字符串,StringBuffer是线程安全的,因此有一些开销,除非您需要,否则您不应该为此付费。StringBuilder具有相同的API,但不是线程安全的(即,您应该只在单个线程内部使用它)


是的,如果您正在构建大型字符串,则使用StringBuilder更有效。作为API的一部分传递StringBuilder或StringBuffer可能不值得。这太令人困惑了。

是的,您每次都将使用+=,创建一个新对象。然而,这并不意味着它总是错误的。这取决于您是希望将该值作为字符串,还是只想使用它进一步构建字符串

如果您确实希望将
x+y
的结果作为字符串,那么您也可以使用字符串串联。但是,如果您真的要(比如)循环并附加另一个字符串,以及另一个字符串,等等-只需要在最后将结果作为一个字符串,那么StringBuffer/StringBuilder就是最好的选择。事实上,循环是StringBuilder比字符串连接更有效的地方——5次甚至10次直接连接的性能差异将非常小,但对于数千次直接连接来说,性能差得多——基本上是因为连接的复杂度为O(N2),而StringBuilder的复杂度为O(N)

在Java5和更高版本中,基本上应该使用StringBuilder——它是不同步的,但这几乎总是可以的;想要在线程之间共享一个线程是非常罕见的


我有一个你可能会觉得有用的方法。

经验法则很简单:

如果在循环中运行串联,请不要使用
+=


如果您不是在循环中运行串联,那么使用
+=
根本不重要。(除非性能关键型应用程序认为字符串是不可变的,否则您是对的,因此如果您在执行大量字符串连接时试图节省内存,则应使用StringBuilder而不是+=


但是,您可能不介意。程序是为其人类读者编写的,因此您可以清晰地阅读。如果优化很重要,您应该首先进行分析。除非您的程序非常重视字符串活动,否则可能会有其他瓶颈。

我同意上面发布的所有答案,但这会对您有所帮助您需要稍微了解一下Java的实现方式。JVM在内部使用StringBuffers来编译String+运算符(从中):

字符串缓冲区由 编译器来实现二进制代码 字符串串联运算符+。用于 例如,代码:

     x = "a" + 4 + "c"
编译为等效于:

     x = new StringBuffer().append("a").append(4).append("c")
                           .toString()
同样地,
x+=“somenewstring”
相当于
x=x+“somenewstring”
。你明白我的意思了吗

如果要进行大量的字符串连接,使用StringBuffer将提高性能,但是如果只进行几个简单的字符串连接,Java编译器可能会为您进行优化,并且您不会注意到性能上的差异


它不会占用更多内存。是的,会创建新对象,但会回收旧对象。最终,使用的内存量是相同的。

StringBuffer一直都是同步的-他们没有让它在Java 5中同步,这就是他们引入StringBuilder的原因。这比我以前认为的更有意义。我不知道ced注意到文档从1.4更改为5,现在更突出地提到了线程安全。当您执行大量字符串操作时,No+=不会更快,StringBuffer会更快。您对GC的看法是正确的,它可能会正确地处理所有废弃的字符串对象,但仍然存在创建对象的成本ion..问题不在于垃圾本身。杀死你的是所有的字符复制!使用
+=
copies
O(N^2)将N个字符串接为1个字符串
characters。我不太确定。一些字符串会在Perm空间中结束,据我所知,该区域没有垃圾收集器。字符串对象通过使用string.intern()进入池。如果您在
string
上调用
intern()
,则