W3docs

Типы данных Java

Изучите примитивные типы данных Java (byte, short, int, long, float, double, char, boolean) и ссылочные типы.

Java — статически типизированный язык: каждая переменная имеет тип, известный на этапе компиляции. Типы делятся на два семейства: примитивы (встроенные в язык исходные значения) и ссылочные типы (объекты, массивы, всё, что создаётся с помощью new). В этой главе разбираются оба семейства.

Восемь примитивных типов

Примитивы — единственные значения в Java, которые не являются объектами. Они хранят своё значение непосредственно в ячейке памяти переменной. В Java определено ровно восемь примитивных типов:

ТипРазмерДиапазонЗначение по умолчаниюПример литерала
byte8 бит-128 до 1270byte b = 100;
short16 бит-32 768 до 32 7670short s = 30000;
int32 бита-2³¹ до 2³¹-1 (≈ ±2,1 млрд)0int i = 1_000_000;
long64 бита-2⁶³ до 2⁶³-10Llong l = 9_000L;
float32 битаIEEE 754, одинарная точность0.0ffloat f = 3.14f;
double64 битаIEEE 754, двойная точность0.0double d = 3.14;
char16 битКодовая единица Unicode (U+0000 до U+FFFF)\0char c = 'A';
booleanЗависит от JVMtrue или falsefalseboolean b = true;

Несколько вещей, которые стоит запомнить:

  • int — стандартный целочисленный тип. Большинство счётчиков и индексов используют int. long следует применять только тогда, когда действительно нужны числа выше ~2 миллиардов.
  • double — стандартный тип с плавающей точкой. Просто написанное 3.14 — это double; 3.14f — это float. Используйте double, если только нехватка памяти не вынуждает перейти на float.
  • Подчёркивания в числовых литералах улучшают читаемость: 1_000_000 — то же самое, что 1000000.
  • Значения по умолчанию применяются только к полям, а не к локальным переменным. У локальной переменной нет значения по умолчанию — её необходимо инициализировать перед чтением.

Ссылочные типы

Всё остальное — String, массивы, ваши собственные классы, библиотечные классы — является ссылочным типом. Переменная ссылочного типа не хранит сам объект; она хранит ссылку (по сути, указатель) на объект в куче:

String name = "Ada";
int[] scores = new int[10];
LocalDate today = LocalDate.now();

Значение по умолчанию любой ссылочной переменной — null, специальное значение, означающее «нет объекта».

String s = null;
System.out.println(s.length());  // throws NullPointerException at runtime

null — источник одной из самых распространённых ошибок времени выполнения в Java. Глава Исключения Java объясняет, как обрабатывать возникающее при этом исключение NullPointerException.

Классы-обёртки

Каждому примитиву соответствует класс-обёртка — настоящий объект, обёртывающий примитивное значение:

ПримитивОбёртка
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

Обёртки нужны, когда требуется помещать примитивы в коллекции (которые принимают только объекты):

List<Integer> scores = new ArrayList<>();
scores.add(42);   // autoboxed from int → Integer
int first = scores.get(0);  // unboxed from Integer → int

Java автоматически преобразует примитивы в обёртки и обратно — этот механизм называется автоупаковкой (autoboxing) и распаковкой (unboxing), — поэтому в большинстве случаев вы этого не замечаете.

Замечание о String

String — ссылочный тип, а не примитив. Он достаточно особенный, чтобы язык предоставил для него синтаксис литерала ("text") и оператор +. Строки неизменяемы — после создания их содержимое никогда не меняется. Каждое «изменение» возвращает новую строку. Глава Строки Java рассматривает эту тему подробно.

Выбор типа

Краткое дерево решений для повседневного Java:

  • Подсчёт элементов или индексы массивовint
  • Большие числа (размеры файлов, временные метки в миллисекундах)long
  • ДеньгиBigDecimal (не double — округление с плавающей точкой вас подведёт)
  • Один символchar
  • Да/нетboolean
  • ТекстString
  • Дата или время → типы из java.time (LocalDate, Instant, Duration)

Не поддавайтесь желанию «сэкономить память», используя byte или short для обычных целых чисел. JVM оптимизирована под операции с int; short в большинстве случаев реально не экономит память.

Распространённые ловушки

Несколько особенностей поведения типов регулярно удивляют новичков. Знание их заранее экономит часы отладки.

Переполнение целых чисел происходит незаметно

Целочисленная арифметика в Java никогда не выбрасывает исключение при переполнении — она просто циклически обнуляется. Прибавление 1 к наибольшему int даёт наименьший int:

int max = Integer.MAX_VALUE;   // 2147483647
System.out.println(max + 1);   // -2147483648

Если значение может превысить ~2,1 миллиарда, используйте long. Для чисел, способных переполнить даже long, воспользуйтесь BigInteger.

Плавающая точка не является точной

float и double следуют стандарту IEEE 754, который не может точно представить большинство десятичных дробей. Классический пример:

System.out.println(0.1 + 0.2);   // 0.30000000000000004

Именно поэтому не следует использовать double для денег. Используйте BigDecimal (создавая его из String, например new BigDecimal("0.1")), когда важны точные десятичные значения.

char — это число

char — беззнаковое 16-битное целое число, хранящее кодовую единицу Unicode, поэтому он участвует в арифметических операциях:

char a = 'A';
System.out.println((int) a);   // 65
System.out.println((char) (a + 1));  // B

Сравнивайте обёртки с помощью .equals(), а не ==

== для объектов-обёрток сравнивает ссылки, а не значения. Из-за кэширования при автоупаковке для небольших значений Integer (от -128 до 127) оператор == кажется работающим для малых чисел, но затем даёт сбой для больших:

Integer a = 127, b = 127;
System.out.println(a == b);   // true  (cached)
Integer c = 128, d = 128;
System.out.println(c == d);   // false (different objects)
System.out.println(c.equals(d));  // true  (compares values)

Всегда используйте .equals() для сравнения значений обёрток. В главе Приведение типов Java описаны правила преобразования между этими типами.

Рабочая демонстрация

java— editable, runs on the server

Что дальше

В главе Приведение типов Java показано, как выполнять преобразование между числовыми типами и связанными ссылочными типами.

Практика

Практика
Какие утверждения о типах данных Java верны?
Какие утверждения о типах данных Java верны?
Was this page helpful?