Я начал учить Java и не могу понять один момент. Просматривая очередной видеоурок я услышал, что "При создании переменной одного из ссылочных типов происходит создание ячейки памяти, содержащей ссылку на произвольный объект в памяти. Когда мы присваиваем значение этой ссылочной переменной в другую переменную, происходит копирование ссылки и мы получаем вторую ссылку, указывающую на тот же объект"
Далее сказано, что "Если объект модифицировать через вторую ссылку, то изменения будут видны и через первую ссылку, потому что это тот же самый объект"
Я это понял так, что в памяти есть один и тот же объект, на который могут ссылаться несколько переменных. Соответственно при изменении одной переменной, ссылающейся на данный объект, будут изменены и значения всех других переменных, ссылающихся на этот же объект
Решив проверить это опытным путем я тут же написал короткий код:
public class Main {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = s1;
s2 += "!";
System.out.println("s1 = " + s1 + "\n" + "s2 = " + s2);
}
}
Сначала я создая переменную s1
ссылочного типа String
и присваиваю ей произвольное значение. После этого, создаю новую переменную s2
и приравниваю ее к s1
. Как я понял, должно происходить копирование ссылки, и в итоге обе переменные должны ссылаться на один и тот же объект строки в памяти. Соответственно, при изменении этого объекта в памяти через одну переменную, изменения должны быть видны и через другую, но этого не происходит - ниже представлен вывод этой программы
>>> s1 = Hello
>>> s2 = Hello!
Почему изменение объекта, на который ссылается s1
не привело к изменению объекта, на который ссылается s2
, учитывая, что они должны ссылаться на один и тот же объект в памяти?
Объекты типа String в Java - неизменяемы. Когда вы вносите изменение в объект типа String с помощью одного из методов этого класса или с помощью конкатенации (в вашем случае - для изменения строки используется конкатенация: s2 += "!";) - тогда создается НОВЫЙ объект класса String который будет представлять собой (по содержанию символов) старую строку с внесенными изменениями. В строке s2 += "!"; вы как раз создаете ещё одну строку и присваиваете переменной s2 ссылку на эту новую строку. При этом ссылка s1 попрежнему ссылается на объект строки созданный вами раннее.
Попробуйте провести ваш маленький эксперимент с типом StringBuilder (этот тип данных представляет собой как раз таки изменяемую строку).
Объект String
является неизменяемым. Несмотря на то, что переменные типа String
являются ссылочными, при их изменении создается новый объект и новая переменная по ссылке указывает уже на него(а не на тот объект, который был взят для изменения).
Примитивные типы Java не являются объектами. К ним относятся:
boolean
- булев тип, может иметь значения true или false
byte
- 8-разрядное целое число
short
- 16-разрядное целое число
int
- 32-разрядное целое число
long
- 64-разрядное целое число
char
- 16-разрядное беззнаковое целое, представляющее собой символ UTF-16 (буквы и цифры)
float
- 32-разрядное число в формате IEEE 754 с плавающей точкой
double
- 64-разрядное число в формате IEEE 754 с плавающей точкой
Все остальные типы являются ссылочными. Подробнее здесь
Тип String
неизменяемый. При попытке изменения значения переменных этого типа, в памяти будет создаваться новый объект
Изменяемым типом является к примеру ArrayList
или StringBuilder
, использующийся ниже в примере
Подробнее здесь
Желаемое поведение программы достигается, при использовании ссылочных, изменяемых типов(String
- ссылочный, неизменяемый)
Перепишем программу с использованием изменяемого аналога String
- StringBuilder
:
public class Main {
public static void main(String[] args) {
// Создаём изменяемый объект типа `StringBuilder`
StringBuilder s1 = new StringBuilder("Hello");
// s2 - ссылка на s1
StringBuilder s2 = s1;
// `StringBuilder` - изменяемый,
// поэтому нового объекта не создается
s2.append("!");
// При изменении объекта, изменились значения
// и всех ссылающихся на него переменных
System.out.println("s1 = " + s1 + "\n" + "s2 = " + s2);
}
}
Вывод:
>>> s1 = Hello!
>>> s2 = Hello!
Подробнее про StringBuilder
здесь
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Нужно чтобы клиент постоянно находился в режиме ожидания ввода команд со стороны пользователяЭти команды затем отправляются на сервер
При столкновении с другим телом ball либо останавливается, либо двигается вдоль негоВроде как это может происходить из-за неправильного world scale,...
Пытаюсь получить строковую переменную из "TextField" и передать ее в создаваемый файл MS Word
Пробую делать мини приложение, что-то типа доски объявленийНи как не получается у меня сделать поиск по фильтру