1

我有点困惑,显然在这里遗漏了一些东西:

我读到 java.lang.String 的“是常量;它们的值在创建后不能更改”。

但是,如果我编写以下代码:

String line;
line = "Test1";
System.out.println(line);
line = "Test2";     
System.out.println(line);

终端输出:

Test1
Test2

看来我可以设置一个值,然后稍后为该字符串设置另一个值。

如果我尝试这种方式没有区别:

String line2 = "Test3";
System.out.println(line2);
line2 = "Test4";
System.out.println(line2);

在最初设置后,我仍然可以设置该值。

我在这里哪里出错了?

谢谢。

4

5 回答 5

4

字符串是不可变的,它们的值不能更改。那是真实的。

但是在您的代码中,您正在使用引用。

String line; //allocate variable
line = "Test1"; //assign to variable value "Test1"
System.out.println(line);
line = "Test2"; //assign to variable value "Test2"

您无法更改的是字符串本身而不是变量引用。

详细JLS 15.26

这适用于对象类型和原语。

于 2013-09-10T21:11:38.797 回答
3

在JVM Test1 和Test2 的堆内存中创建并分配了两个String 值。您所做的只是更改参考地址。这是您的代码语句的字节码。请只关注ldc操作码,因为您可以看到它lcd得到不同的字符串引用。

public class JavaConstant extends java.lang.Object {
  public JavaConstant();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16                 // String Test1
       2: astore_1
       3: getstatic     #18                 // Field java/lang/System.out:Ljava/io/PrintStream;
       6: aload_1
       7: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String
;)V
      10: ldc           #30                 // String Test2
      12: astore_1
      13: getstatic     #18                 // Field java/lang/System.out:Ljava/io/PrintStream;
      16: aload_1
      17: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String
;)V
      20: return
}
于 2013-09-10T21:10:26.047 回答
2

看评论

String line; // declares a variable of type String
line = "Test1";  // creates a new String object with value "Test1" and makes line reference it
System.out.println(line); // don't care
line = "Test2";  // creates a new String object with value "Test2" and makes line reference it

这是两个不同的对象。

改变它的价值会做这样的事情

line = "Test1";
line[4] = "2";
System.out.println(line); // printing Test2

这在 Java 中是不可能的,因为String会产生不可变的实例。

分配引用和更改对象的值是有区别的。

于 2013-09-10T21:11:24.737 回答
1

字符串是不可变的。您无法更改 String 的值。您创建一个新的字符串对象或从字符串池中引用它。

String line;                   // line is at Location A
line = "Test1";               // Location A --> "Test1"
System.out.println(line);    // Prints Test1
line = "Test2";              // Location A --> "Test2" --> Reference to Test1 is lost
System.out.println(line);   // Prints Test2
于 2013-09-10T21:13:52.337 回答
1

上面的所有答案都是正确的,字符串是不可变的,你不能编辑对象,另一方面你可以删除它们或编辑它们的引用。

垃圾收集器将删除所有没有引用的对象,因为它们不能再使用了。

Java中有两种内存:堆和栈。对象存在于堆中,而变量存在于栈中。

当你创建

String test1="Test1"

test1 位于堆栈中,可以更改

但是“Test1”不在堆栈中,您无法对其进行编辑。

String test1, test2;

test1 = test2 = "MyString"

如果您更改 test1="Hello" test2 将不会受到影响,字符串本身也不会受到影响。

Person person1, person2;
person1 = person2 = new Person("Nickname")

person1.rename("My new name");

另一方面,将编辑 Person 的名称(位于堆中的对象)

它不需要更改堆栈引用,并且 person1 和 person2 都将受到此更改的“影响”。

于 2013-09-10T21:19:28.830 回答