Код, который вы разместили выше, на самом деле не изменяет никакие строки, хотя выглядит так.Причина в том, что эта строка не изменяет строку:
string = string + "bcd";
Вместо этого она делает следующее:
- Создайте новую строку со значением
string + "bcd"
. - Измените, на какую строку ссылается
string
, чтобы ссылаться на эту новую строку.
Другими словами, сами объекты конкретной конкретной строки не были изменены, но ссылки на эти строки действительно были изменены.Неизменяемость в Java обычно означает, что объекты не могут быть изменены, а не ссылки на эти объекты.
Важная деталь, которая смущает многих новых Java-программистов, состоит в том, что приведенная выше строка часто пишется как
string += "bcd";
, который выглядит еще сильнее, как будто он объединяет bcd
в конец строки и, таким образом, изменяет его, даже если он эквивалентен приведенному выше коду и, следовательно, не вызывает никаких изменений в реальном объекте String
(опять же, он работает путем создания нового String
объекта и изменения объекта, на который ссылается ссылка.)
Чтобы увидеть, что здесь происходит, вы фактически изменяете ссылку, а не строку, на которую она ссылаетсяк, вы можете попробовать переписать код, чтобы сделать string
final
, который не позволяет вам изменять, на какой объект ссылаются.Если вы сделаете это, вы обнаружите, что код больше не компилируется.Например:
class toString{
public static void main(String[] args){
final String string = "abc";
string = string + "bcd"; // Error: can't change string!
System.out.println(string);
}
}
Последнее замечание. Еще одна распространенная причина скорби для новых Java-программистов при использовании String
s заключается в том, что String
имеет методы, которые выглядят как видоизменяющие строку, но в действительности их нет.Например, этот код не работает правильно:
String s = "HELLO, WORLD!";
s.toLowerCase(); // Legal but incorrect
System.out.println(s); // Prints HELLO, WORLD!
Здесь вызов s.toLowerCase()
фактически не преобразует символы строки в нижний регистр, а вместо этого создает новую строку с набором символовв нижнем регистре.Если затем переписать код как
String s = "HELLO, WORLD!";
s = s.toLowerCase(); // Legal and correct
System.out.println(s); // Prints hello, world!
, тогда код будет работать правильно.Опять же, ключевая деталь здесь в том, что присвоение s
не меняет какой-либо конкретный объект String
, а просто настраивает, к какому объекту относится s
.
Надеюсь, это поможет!