Java 字符串变量设置 - 引用还是值?

2022-09-02 22:47:59

以下 Java 代码段来自 AP 计算机科学实践考试。

String s1 = "ab";
String s2 = s1;
s1 = s1 + "c";
System.out.println(s1 + " " + s2);

此代码的输出是 BlueJ 上的“abc ab”。但是,一个可能的答案选择是“abc abc”。答案可以取决于 Java 是像基元类型(按值)还是像对象(按引用)一样设置字符串引用。

为了进一步说明这一点,让我们看一个基元类型的例子:

int s1 = 1;
int s2 = s1; // copies value, not reference
s1 = 42;

System.out.println(s1 + " " + s2); // prints "1 42"

但是,假设我们有持有余额的BankAccount对象

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter
BankAccount b2 = b1; // reference to the same object
b1.setBalance(0);
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 0"

我不确定字符串是哪种情况。从技术上讲,它们是对象,但是我的编译器在相互设置变量时似乎将它们视为基元类型。

如果Java像基元类型一样传递字符串变量,答案是“abc ab”。但是,如果Java将字符串变量视为对任何其他对象的引用,则答案将是“abc abc”。

您认为哪个是正确的答案?


答案 1

java 字符串是不可变的,因此重新分配实际上会导致变量指向 String 的新实例,而不是更改 String 的值。

String s1 = "ab";
String s2 = s1;
s1 = s1 + "c";
System.out.println(s1 + " " + s2);

在第 2 行, s1 == s2 和 s1.等于(s2)。在第 3 行进行串联后,s1 现在引用具有不同不可变值“abc”的实例,因此 s1==s2 和 s1.equals(s2) 都不会。


答案 2

您的 BankAccount 和 String 之间的区别在于 String 是不可变的。没有“setValue()”或“setContent()”这样的东西。您的银行帐户的等效示例是:

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter
BankAccount b2 = b1; // reference to the same object
b1 = new BankAccount(0);
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 500"

因此,如果您以这种方式思考(实际上不是编译器所做的,而是功能等效的),字符串串联方案是:

String s1 = "ab";
String s2 = s1;
s1 = new String("abc");
System.out.println(s1 + " " + s2); //prints "abc ab"