【问题标题】:Java: Is "new String(oldString)" necessary? (Is String a reference or a value?)Java:“新字符串(旧字符串)”是否必要? (String 是引用还是值?)
【发布时间】:2021-01-21 17:46:36
【问题描述】:

我正在编写一个处理字符串的方法(以提取某些内容):
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);,这应该使用来自 myInput 的数据创建一个新的 String 对象,但我可以随意操作 workString,而不必担心我正在对在别处使用的对象。

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

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

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

【问题讨论】:

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

标签: java string object pass-by-reference pass-by-value


【解决方案1】:

正如@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) 且无法访问,因此它们是垃圾收集的候选对象。
最后只有两个String 会在池中:Hello World !(这两个文字)。

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

如果您的答案仅涉及字符串对象或所有对象,您能否也请简要提及一下

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

回答你的标题:

需要“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)但都指向相同的值。

【讨论】:

  • 额外的部分非常有趣,谢谢!
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2011-03-03
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    相关资源
    最近更新 更多