Java String "постоянная" путаница

Я немного смущен и явно что-то пропустил:

Я читал, что 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);

Я все еще могу установить значение после его установки изначально.

Где я здесь ошибся?

Благодарю.

5 ответов

См. Комментарии

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 создает неизменяемые экземпляры.

Там есть разница между назначением ссылок и изменением значения объекта.


Строка неизменяема, их значения не могут быть изменены. Это правда.

Но в коде вы работаете со ссылками.

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

Это относится к типам объектов и примитивам.


Создано два значения String и выделено пространство в кучевой памяти в JVM Test1 и Test2. То, что вы делаете, это просто изменение ссылочного адреса. Вот байт-код ваших операторов кода. Пожалуйста, просто сосредоточьтесь на ldc opcode, так как вы можете видеть, что lcd получает другую ссылку на String.

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
}
</init>


Все приведенные выше ответы правильны, String неизменен, и вы не можете редактировать объект, ссылки в другой руке вы можете удалить или изменить.

Сборщик мусора удалит все объекты, у которых нет ссылок, поскольку они больше не могут использоваться.

В Java есть 2 памяти: куча и стек. Объект находится в куче, а переменные - в стеке.

Когда вы создаете

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");

Там в другой руке будет редактировать имя Лица (объект, который живет в куче)

Не нужно было менять ссылку на Stack, и эти изменения будут затронуты как person1, так и person2.


Строки неизменяемы.Вы не можете изменить значение String.Вы создаете новый объект String или ссылаетесь на него из пула 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

licensed under cc by-sa 3.0 with attribution.