问题描述
我正在编写一个处理字符串的方法(以提取某些内容):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-rld
和 Hell- W-rld !
不是字面量 (GC of String literals) 且不再可达,因此它们是垃圾收集的候选对象。
最后,池中只有两个 String
:Hello World
和 !
(两个文字)。
编辑:“o”和“-”也将留在池中,因为它们也是文字
如果您的回答是关于 String 对象还是所有对象,能否请您简要提及
这取决于属性,
String is not a Primitive 但在某些方面被视为一回事。 Primitives are immutable 和 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
String
通过引用传递,new
分配一个新引用(指向池中的同一个 String
)。两个引用不同(s1
和 s2
),但都指向相同的值。
正如 correct Answer by IQbrod 所说,String
是不可变的。因此无需担心更改其包含的文本。
如果您确实想更改容器文本,而不是使用 String
类,您可以使用接口 CharSequence
的另一个实现。
这是我制作的图表,旨在为您提供各种与文本相关的类的概览,并帮助您针对特定目的选择一个类。