Java:是否需要“new String(oldString)”? 字符串是引用还是值?

问题描述

我正在编写一个处理字符串的方法(以提取某些内容):
public static String myProcessor (String myInput) {...

我想在这方法中有一些 String 对象,我可以在 (workString = workString.replace(...) 上应用我的转换

但是,我不想更改原始字符串(通过对我的方法的引用,即:
myProcessor(originalString)) - 因为在我的方法调用之后可能会有方法调用,它也想在我的方法调用之前从原始字符串中处理/提取一些东西

我仍在学习 Java,根据我的书 (Deitel & Deitel - "Java How To Program"):
〜“原始类型是按值传递。其他变量类型用于对象,而这些变量类型是按引用传递,因此对象的变量赋值是将引用传递给同一对象。一个变量引用的对象发生变化读取另一个变量时可以看到(如果Object var2 = var1)"
(这不是逐字逐句,只是我从中了解到的!)

所以,我想我会尝试:String workString = new String(myInput); 这应该创建一个新的 String 对象,使用来自 myInput 的数据,但我可以随意操作 workString,而无需担心我正在对在别处使用的对象进行更改。

IntelliJ 建议这是多余的,我可以这样做:String workString = myInput,这让我感到困惑...

IntelliJ 在这里吗?
实际上,我什至需要创建一个局部范围的 workString,或者一旦变量“到达”到方法中就“分离”引用? (即:在 myProcessor 内部,myInput 不再持有 originalString 调用中对 myProcessor 的引用,但它创建了一个新的 String 对象?

如果您的回答仅涉及 String 对象或所有对象,能否请您简要提及?
我有一种感觉,也许 String 介于原始类型和对象类型之间,并且对其应用了特殊规则...

解决方法

正如@AndyTurner 所提到的, 在 Java 中,String 是不可变的,这意味着对 String 的任何操作都不会改变 原始 String

例如:

myString = "Hello World"; // literal
myString = myString.replace("o","-"); // not literal
myString = myString + " !"; // not literal

Hello World 放置在字符串池中并分配给变量 myString
Hell- W-rld 放置在字符串池中并分配给变量 myString
Hell- W-rld ! 放置在字符串池中并分配给变量 myString

但是! 由于 Hell- W-rldHell- W-rld ! 不是字面量 (GC of String literals) 且不再可达,因此它们是垃圾收集的候选对象。
最后,池中只有两个 StringHello World !(两个文字)。

编辑:“o”和“-”也将留在池中,因为它们也是文字

如果您的回答是关于 String 对象还是所有对象,能否请您简要提及

这取决于属性, String is not a Primitive 但在某些方面被视为一回事。 Primitives are immutableString 也是如此。

回答你的标题:

是否需要“new String(oldString)”? (String 是引用还是值?)

它允许将值存储在字符串池中,但是:

String s1 = "Hi";
String s2 = new String(s1); // Any other operation would assign a new reference as String is immutable
s1 == s2; // false
s1.equals(s2); // true

String 通过引用传递,new 分配一个新引用(指向池中的同一个 String)。两个引用不同(s1s2),但都指向相同的值。

,

正如 correct Answer by IQbrod 所说,String 是不可变的。因此无需担心更改其包含的文本。

如果您确实想更改容器文本,而不是使用 String 类,您可以使用接口 CharSequence 的另一个实现。

这是我制作的图表,旨在为您提供各种与文本相关的类的概览,并帮助您针对特定目的选择一个类。

enter image description here