Типы данных в Java: какие бывают, чем различаются и что такое ссылки и примитивы
Рассказываем, как джависту не запутаться во всех этих byte, short, boolean, char и String.
Основа любого языка программирования — данные и операции с ними. Java не исключение. Это строго типизированный язык, поэтому типы данных значат в нём очень многое.
Java следит за тем, чтобы все переменные, выражения и значения соответствовали своему типу данных. Поэтому операции, которые допустимы для одного типа, нельзя провести с другим — тип переменной определяет, какие операции с ней можно выполнить.
Когда код на Java компилируется, машина проверяет соответствие типов операндов во всех методах, конструкторах и других операторах. Если в программе есть хотя бы одна недопустимая операция, компилятор не превратит её в байт-код. Поэтому контроль типов данных помогает уменьшить количество ошибок при написании программы.
В этой статье мы рассмотрим:
- какие типы данных есть в Java;
- чем различаются примитивные и ссылочные переменные;
- какие у переменных бывают значения по умолчанию;
- как упаковка и распаковка помогают превратить примитивные переменные в объект.
Какие типы данных есть в Java
В Java типы данных делят на две большие группы: примитивные и ссылочные. В состав примитивных типов (или просто примитивов) входят четыре подвида и восемь типов данных:
1) целые числа (byte, short, int, long);
2) числа с плавающей точкой (float, double);
3) логический (boolean);
4) символьный (char).
Ссылочные типы данных ещё называют ссылками. К ним относятся все классы, интерфейсы, массивы, а также тип данных String.
Хотя у примитивов и ссылок много общего, между ними есть существенные различия. И главное различие — в том, что именно в них хранится.
Примитивные переменные | Ссылочные переменные |
---|---|
Хранят значение | Хранят адрес объекта в памяти, на который ссылаются (отсюда и название). Используются для доступа к объектам (его нельзя получить, если на объект нет ссылки) |
Создаются присваиванием значения | Создаются через конструкторы классов (присваивание только создаёт вторую ссылку на существующий объект) |
Имеют строго заданный диапазон допустимых значений | По умолчанию их значение — null |
В аргументы методов попадают копии значения переменной (это передача по значению) | В методы передаётся значение ссылки — операция выполняется над оригинальным объектом, на который ссылается переменная |
Могут использоваться для ссылки на любой объект объявленного или совместимого типа |
Вот пример использования примитивных и ссылочных типов данных:
Значения переменных по умолчанию
Как мы уже отмечали, в зависимости от типа данных у каждой переменной есть значение по умолчанию. Оно присваивается при её создании.
В этом примере значения по умолчанию получат все переменные:
А в этом примере значения получают только переменные класса: когда мы создадим класс Cat, по умолчанию weight будет равен 0.0.
Но локальные переменные нужно инициировать сразу при создании. Если написать просто int sum; , компилятор выдаст ошибку: java: variable a might not have been initialized.
У примитивов есть строгие рамки допустимых значений по умолчанию и диапазоны значений — для удобства мы собрали их в таблицу.
Как используют целочисленные переменные
Целочисленные типы данных различаются только диапазонами значений. Их основная задача — хранить информацию для вычислений.
Тип byte. Эти переменные используют, чтобы работать с потоком данных, который получили из файла или по сети.
Тип short. По сравнению с byte у него увеличенный, но всё же ограниченный диапазон значений. Применяют short редко — например, когда нужно экономить память.
Тип int. В языке Java int — самый популярный тип целочисленных данных. При вычислениях в виртуальной машине остальные целочисленные типы (byte, short) занимают столько же памяти, сколько int.
Множество классов в Java обладают значениями типа int — например, длина массива внутри класса String выражается целочисленным значением int:
Если переменная хранит количество элементов в коллекциях List, Set и Map, она тоже относится к типу int:
Тип возвращаемого значения подсказывает, сколько элементов можно хранить в списке или множестве. Максимум для int — 2 147 483 647.
Тип long применяют, когда нужно работать с большими целочисленными значениями.
По умолчанию компилятор воспринимает целое число как int, а 9 223 372 036 854 намного больше его максимального значения, поэтому в коде программы нужно явно указать тип long.
Зачем нужны числа с плавающей точкой
Тип данных double используют для работы с десятичными числами.
Тип float используют как экономичный вариант хранения больших массивов данных с плавающей точкой.
Когда переменной присваивают тип float, язык Java воспринимает её как тип данных double. Чтобы этого не происходило, нужно добавлять в конце переменной символ f или F.
Даже если у переменных float и double будут одинаковые значения, язык Java обработает их по-разному, поэтому они будут занимать разный объём памяти.
Не стоит использовать float, когда в вычислениях нужна точность больше пяти знаков после запятой. Oracle пишет об этом в статье «Primitive Data Types».
Логический и символьный типы данных
Чтобы работать с логическими значениями, используют тип данных boolean — это его единственное применение. У такой переменной может быть только два значения: false (ложь) и true (истина).
В Java boolean — отдельная переменная. Это не аналог 1 или 0, как, например, в JavaScript и PHP.
Тип данных char используют, чтобы хранить в переменных любые 16-разрядные символы Unicode. Но их нужно записывать строго в одинарные кавычки ' ', и только по одному.
Не стоит путать символьные и строковые переменные — 'ж' не равно "ж", потому что в двойных кавычках хранится тип данных String. А это уже не примитив.
Пример кода
Вывод в консоли
Значения по умолчанию для ссылочных типов данных
В плане дефолтных значений ссылочные переменные проще примитивов. По умолчанию их значение — null: это означает отсутствие ссылки или то, что ссылка ни на что не указывает.
Но если вызвать метод объекта от переменной со значением null, это приведёт к ошибке NullPointerException:
В ссылочные типы данных входит и String — это класс из стандартной библиотеки Java. Он не относится к примитивам, но его повсеместно используют, чтобы хранить текстовые данные.
Пример использования String:
Строчные переменные можно склеивать оператором +, который используют для конкатенации.
Пример кода
Вывод в консоли
Boxing и unboxing — как превратить примитив в объект
Иногда с примитивами приходится работать как с объектами — например, передавать им значение по ссылке или создавать список из чисел (а списки работают только с объектами).
Поэтому у каждого примитива есть соответствующий ему ссылочный тип — его называют классом-обёрткой. В таких классах хранятся методы для преобразования типов данных, а также другие константы и методы, которые применяются при работе с примитивами.
Тип данных | Класс-обёртка |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
Ссылочные типы данных (обёртки) пишут с прописной буквы, потому что это полноценные классы. А в Java названия всех классов должны начинаться с большой буквы — язык чувствителен к регистру.
Чтобы создать ссылку на примитивный тип данных, нужно использовать соответствующую обёртку:
Если использовать valueOf, процесс упаковывания становится проще и быстрее, потому что он проводит кэширование и потребляет меньше памяти, а конструктор всегда создаёт новый объект.
Классы-обёртки полезны, когда нужно одновременно работать и с числами, и с объектами — например, в коллекциях.
В этой статье мы рассмотрели примитивные типы данных (byte, short, int, long, float, double, char и boolean), ссылочные типы данных (String и остальные). Вы узнали, чем они отличаются друг от друга и какие значения принимают по умолчанию.
В следующей статье мы расскажем, что можно делать с этими переменными с помощью арифметических и логических операторов языка Java.