Java:需要“new String(oldString)”吗?(String 是引用还是值?

Java: Is "new String(oldString)" necessary? (Is String a reference or a value?)

提问人:DraxDomax 提问时间:1/22/2021 最后编辑:DraxDomax 更新时间:1/22/2021 访问量:486

问:

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

我想在这个方法中有一些 String 对象,我可以在 (workString = workString.replace(...)

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

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

所以,我想我会尝试:这应该创建一个新的 String 对象,使用来自的数据,但我可以随心所欲地操作,而不必担心我正在对其他地方使用的对象进行更改。String workString = new String(myInput);myInputworkString

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

IntelliJ 就在这里吗?
实际上,我是否需要创建一个局部范围,或者一旦变量“到达”方法,引用就会“分离”?(即:在里面,不再持有对 from 调用的引用,而是创建一个新的 String 对象?
workStringmyProcessormyInputoriginalStringmyProcessor

您能否简要提及您的答案是仅涉及 String 对象还是所有对象?
我有一种感觉,也许 String 介于 Primitive 类型和 Object 类型之间,并且应用了特殊的规则......

Java 字符串 对象 Pass-by-Reference Pass-By-value

评论

0赞 M A 1/22/2021
在 Java 中,一切都是按值传递的:stackoverflow.com/questions/40480/......
2赞 Andy Turner 1/22/2021
此外,它是不可变的,因此复制它很少会得到任何好处。您所做的任何操作都不会更改原始字符串,而是创建一个新字符串。StringworkString
1赞 Andy Turner 1/22/2021
@DraxDomax这不是更改字符串,而是创建一个新字符串并重新分配变量。
2赞 Stephen P 1/22/2021
当您这样做时,您将创建一个新的 String,如前所述,并将 myString 持有的引用替换为对该新 String 的引用;原始字符串保持不变。的调用方仍然看到对他们传递的原始 String 对象的原始引用,因此不受任何影响。myString = myString.replace("x","y")myProcessor(originalString)
2赞 Slaw 1/22/2021
我建议阅读第一条评论中@MAnouti的链接。在 Java 中,一切都是按值传递的。这包括对象和基元。关于对象的细微差别在于,传递的“值”是对对象的引用。这就是为什么如果将 a 传递给方法,向其添加元素,然后在方法的调用方中查询列表,您将看到更改;您已经修改了对象本身。但是,如果执行相同的方法(参数在哪里),则根本不会影响方法的调用方。Listlist = new ArrayList<>();list

答:

3赞 IQbrod 1/22/2021 #1

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

例如:

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

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

但! 由于 和 不是文字(字符串文字的 GC)并且无法访问,因此它们是垃圾回收的候选者。
最后,池中只有两个:和(两个字面意思)。
Hell- W-rldHell- W-rld !StringHello World !

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

您能否简要提及您的答案是否仅涉及 String 对象或所有对象

这取决于属性,String 不是 Primitive,但在某些方面被视为 Primitive。原语是不可变的,s 也是不可变的。String

要回答您的标题:

“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

A 通过引用传递,并分配一个新引用(到池中的相同引用)。两个引用不同 ( 和 ),但都指向相同的值。StringnewStrings1s2

评论

1赞 DraxDomax 1/23/2021
额外的部分非常有趣,谢谢!
2赞 Basil Bourque 1/22/2021 #2

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

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

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

在此处输入图像描述