Без понимания синтаксиса Java невозможно стать серьезным разработчиком, поэтому сегодня мы продолжаем изучать синтаксис. В одной из прошлых статей мы говорor о примитивных переменных, но так How видов переменных два, сегодня мы поговорим о втором виде — ссылочные типы в Java. Итак что это? Зачем нужны ссылочные типы данных в Java? Давайте представим, что у нас есть an object телевизор с некоторыми характеристиками, такими How номер канала, громкость звука и флаг включенности:
public class TV {
int numberOfChannel;
int soundVolume;
boolean isOn;
}
Как простой тип, например, int
, может хранить эти данные? Напомним: одна переменная int
— это 4 byteа. А ведь там внутри есть две переменные (4 byteа + 4 byteа) этого же типа, да ещё и boolean
(+1 byte)... Total — 4 к 9, а ведь How правило, в an objectе хранится намного больше информации. What делать? Нельзя же вложить an object в переменную. На этом моменте в нашей истории появляются ссылочные переменные. Ссылочные переменные хранят address ячейки памяти, в которой расположен определенный an object. То есть это “визитка” с addressом, имея которую мы можем найти наш an object в общей памяти и выполнять с ним некоторые манипуляции. Ссылка на любой an object в Java представляет собой ссылочную переменную. Как бы это выглядело с нашим an objectом телевизора:
TV telly = new TV();
Переменной типа TV с именем telly
мы задаем ссылку на создаваемый an object типа TV. То есть, JVM выделяет память в куче под an object TV, создает его и address на его местоположение в памяти, кладется в переменную telly
, которая хранится в стеке. Подробнее о памяти, а именно — о стеке и еще массе полезного, можно почитать в этой лекции. Переменная типа TV и an object типа TV, заметor? Это неспроста: an objectм определенного типа должны соответствовать переменные того же типа (не считая наследования и реализаций интерфейсов, но сейчас мы это не учитываем). В конце концов, не будем же мы в стаканы наливать суп? Получается, что у нас an object — это телевизор, а ссылочная переменная для него — How бы пульт управления. С помощью этого пульта мы можем взаимодействовать с нашим an objectом и его данными. Например, задать характеристики для нашего телевизора:
telly.isOn = true;
telly.numberOfChannel = 53;
telly.soundVolume = 20;
Тут мы использовали оператор точки .
— чтобы получить доступ и начать использование внутренних элементов an object, на который ссылается переменная. Например, в первой строке мы сказали переменной telly
: “Дай нам внутреннюю переменную isOn
an object, на который ты ссылаешься, и задай ей meaning true” (включи нам телевизор).
Переопределение ссылочных переменных
Допустим, у нас есть две переменные ссылочного типа и an objectы, на которые они ссылаются:
TV firstTV = new TV();
TV secondTV = new TV();
Если мы напишем:
firstTV = secondTV;
это будет означать, что мы первой переменной в качестве значения присвоor копию address (meaning битов address) на второй an object, и теперь обе переменные ссылаются на второй an object (иначе говоря, два пульта от одного и того же телевизора). В тоже время, первый an object остался без переменной, которая на него ссылается. В итоге у нас есть an object, к которому невозможно обратиться, ведь переменная была такой условной ниточкой к нему, без которой он превращается в мусор, просто лежит в памяти и занимает место. Впоследствии этот an object будет уничтожен из памяти сборщиком мусора. Прервать связующую ниточку с an objectом можно и без другой ссылки:
secondTV = null;
В итоге link на an object останется одна — firstTV
, а secondTV
уже ни на кого указывать не будет (что не мешает нам в дальнейшем присвоить ей ссылку на Howой-нибудь an object типа TV).
Класс String
Отдельно хотелось бы упомянуть класс String. Это базовый класс, предназначен для хранения и работы с данными, которые хранятся в виде строки. Пример:
String text = new String("This TV is very loud");
Здесь мы передали строку для хранения в конструкторе an object. Но никто так не делает. Ведь строки можно создавать:
String text = "This TV is very loud";
Гораздо удобнее, правда? По популярности использования String
не уступает примитивным типам, но всё же это класс, и переменная, которая ссылается на него — не примитивного, а ссылочного типа. У String
есть вот такая замечательная возможность конкатенации строк:
String text = "This TV" + " is very loud";
В итоге мы снова получим текст: This TV is very loud
, так How две строки соединятся в одно целое, и переменная будет ссылаться на этот полный текст. Важным нюансом является то, что String
— это неизменяемый класс. What это значит? Возьмем такой пример:
String text = "This TV";
text = text + " is very loud";
Вроде, бы всё просто: объявляем переменную, задаем ей meaning. На следующей строке изменяем его. Но не совсем-то и изменяем. Так How это неизменяемый класс, на второй строке начальное meaning не меняется, а создается новое, которое в свою очередь состоит из первого + " is very loud"
.
Ссылочные константы
В статье про примитивные типы мы затрагивали тему констант. Как же будет себя вести ссылочная переменная, когда мы объявим её final?
final TV telly = new TV();
Возможно, вы подумаете, что это сделает an object неизменяемым. Но нет, это не так. Ссылочная переменная с модификатором final
будет привязана к определенному an objectу без возможности её How-либо отвязать (переопределить or приравнять к null
). То есть, после задания значения такой переменной, code вида:
telly = new TV();
or
telly = null;
будет вызывать ошибку компиляции. То есть final
действует только на ссылку, а на сам an object влияния не оказывает. Если изначально он у нас изменяемый, мы без проблем можем менять его внутреннее состояние:
telly.soundVolume = 30;
Иногда, переменные обозначают How final даже в аргументах метода!
public void enableTV (final TV telly){
telly.isOn = true;
}
Это делается для того, чтобы в процессе написания метода эти аргументы нельзя было переопределить и соответственно создать меньше путаницы. А что если обозначить final
ссылочную переменную, которая ссылается на неизменяемый an object? К примеру String
:
final String PASSWORD = "password";
Как следствие, мы получим константу, аналог констант примитивного типа, ведь тут мы не можем ни переопределить ссылку, ни изменить внутреннее состояние an object (внутренние данные).
Подведем итоги
- Если простые переменные хранят биты значений, то ссылочные переменные хранят биты, представляющие способ получения an object.
- Ссылки на an objectы объявляются лишь для одного вида an objectов.
- Любой класс в Java — это ссылочный тип.
- По умолчанию в Java meaning любой переменной ссылки —
null
. String
— стандартный пример ссылочного типа. Также этот класс является неизменяемым (immutable).- Ссылочные переменные с модификатором
final
привязаны лишь к одному an objectу без возможности переопределения.
GO TO FULL VERSION