Примитивные типы данных
byte, short, int, long, float, double, boolean, char
Материалы
| Тип | Ссылка |
|---|---|
| Документ | Primitive Data Types |
| Видео | Java Data Types |
Java — строго типизированный язык. Каждая переменная должна иметь объявленный тип. В этом разделе мы изучим 8 примитивных типов данных — фундамент Java.
Обзор примитивных типов
Java имеет ровно 8 примитивных типов:
| Тип | Размер | Диапазон значений | Значение по умолчанию |
|---|---|---|---|
byte | 1 байт | -128 … 127 | 0 |
short | 2 байта | -32 768 … 32 767 | 0 |
int | 4 байта | -2 147 483 648 … 2 147 483 647 | 0 |
long | 8 байт | -9 223 372 036 854 775 808 … 9 223 372 036 854 775 807 | 0L |
float | 4 байта | ~±3.4×10^38 (6-7 значащих цифр) | 0.0f |
double | 8 байт | ~±1.7×10^308 (15-17 значащих цифр) | 0.0 |
char | 2 байта | 0 … 65 535 (Unicode) | ‘\u0000’ |
boolean | ~1 бит | true / false | false |
Целочисленные типы
byte
Самый маленький целочисленный тип. Занимает 1 байт.
byte minByte = -128;
byte maxByte = 127;
byte age = 25;
// Полезен для экономии памяти в больших массивах
byte[] buffer = new byte[1024];
short
Редко используется. Занимает 2 байта.
short minShort = -32768;
short maxShort = 32767;
short year = 2024;
int (основной тип)
Самый часто используемый целочисленный тип. Занимает 4 байта.
int count = 0;
int population = 1_000_000; // подчёркивания для читаемости
int negative = -42;
// Диапазон
int min = Integer.MIN_VALUE; // -2147483648
int max = Integer.MAX_VALUE; // 2147483647
По умолчанию все целочисленные литералы имеют тип int:
int x = 100; // 100 — это int
long y = 100; // 100 — всё ещё int, но присваивается в long
// long z = 10000000000; // ОШИБКА! 10 миллиардов не помещается в int
long z = 10000000000L; // OK с суффиксом L
long
Для очень больших чисел. Занимает 8 байт. Требует суффикс L.
long worldPopulation = 8_000_000_000L;
long fileSize = 1099511627776L; // 1 TB в байтах
long timestamp = System.currentTimeMillis();
// Диапазон
long min = Long.MIN_VALUE; // -9223372036854775808
long max = Long.MAX_VALUE; // 9223372036854775807
Важно: Всегда используйте заглавную L, не строчную l (легко спутать с единицей).
long bad = 100l; // работает, но плохо читается
long good = 100L; // чётко видно, что это long
Числа с плавающей точкой
float
Одинарная точность. Занимает 4 байта. Требует суффикс f или F.
float pi = 3.14f;
float temperature = -40.0f;
float price = 19.99F;
// Точность: ~6-7 значащих цифр
float precise = 123456.789f;
System.out.println(precise); // 123456.79 (потеря точности!)
double (основной тип)
Двойная точность. Занимает 8 байт. Используется по умолчанию.
double pi = 3.141592653589793;
double avogadro = 6.022e23; // научная нотация
double planck = 6.626e-34;
// Точность: ~15-17 значащих цифр
double precise = 123456789.123456789;
System.out.println(precise); // 1.2345678912345679E8
По умолчанию все дробные литералы имеют тип double:
double d = 3.14; // OK
// float f = 3.14; // ОШИБКА! 3.14 — это double
float f = 3.14f; // OK с суффиксом f
Специальные значения
double positiveInfinity = Double.POSITIVE_INFINITY; // бесконечность
double negativeInfinity = Double.NEGATIVE_INFINITY;
double notANumber = Double.NaN; // Not a Number
// Примеры
double inf = 1.0 / 0.0; // Infinity
double negInf = -1.0 / 0.0; // -Infinity
double nan = 0.0 / 0.0; // NaN
// Проверка на NaN
Double.isNaN(nan); // true
Double.isInfinite(inf); // true
// Внимание: NaN != NaN
System.out.println(nan == nan); // false!
Проблемы точности
Числа с плавающей точкой не могут точно представить все десятичные дроби:
double a = 0.1;
double b = 0.2;
double c = a + b;
System.out.println(c); // 0.30000000000000004
System.out.println(c == 0.3); // false!
// Правильное сравнение
double epsilon = 1e-10;
System.out.println(Math.abs(c - 0.3) < epsilon); // true
Для финансовых расчётов используйте BigDecimal:
import java.math.BigDecimal;
BigDecimal price = new BigDecimal("19.99");
BigDecimal quantity = new BigDecimal("3");
BigDecimal total = price.multiply(quantity);
System.out.println(total); // 59.97 (точно!)
Символьный тип char
char хранит один Unicode-символ. Занимает 2 байта (16 бит).
char letter = 'A';
char digit = '7';
char cyrillic = 'Я';
char newline = '\n';
Символы как числа
char — это беззнаковое 16-битное целое (0-65535):
char ch = 'A';
System.out.println((int) ch); // 65
char fromCode = 65;
System.out.println(fromCode); // A
// Арифметика с символами
char next = (char) ('A' + 1);
System.out.println(next); // B
Escape-последовательности
| Последовательность | Значение |
|---|---|
\n | Новая строка |
\t | Табуляция |
\r | Возврат каретки |
\\ | Обратный слэш |
\' | Одинарная кавычка |
\" | Двойная кавычка |
\uXXXX | Unicode символ (4 hex цифры) |
char tab = '\t';
char quote = '\'';
char backslash = '\\';
char omega = '\u03A9'; // Ω
char cyrillic = '\u0410'; // А (русская)
Unicode и суррогатные пары
char может хранить только символы из Basic Multilingual Plane (BMP): U+0000 до U+FFFF.
Для символов за пределами BMP (например, emoji) нужны суррогатные пары:
// Emoji U+1F60A (смайлик) не помещается в один char!
// char smile = 0x1F60A; // ОШИБКА! Выход за пределы char
// Используйте String для emoji
String smile = "\uD83D\uDE0A"; // суррогатная пара
System.out.println(smile); // выведет смайлик
// Или используйте code point
int codePoint = 0x1F60A;
String emoji = new String(Character.toChars(codePoint));
System.out.println(emoji);
// Проверка
System.out.println(Character.charCount(0x1F60A)); // 2 (требует 2 char)
System.out.println(Character.charCount('A')); // 1
Логический тип boolean
boolean имеет только два значения: true и false.
boolean isActive = true;
boolean hasPermission = false;
boolean isAdult = age >= 18;
boolean isValid = name != null && !name.isEmpty();
Особенности boolean
В отличие от C/C++, в Java:
booleanнельзя преобразовать в число- Числа нельзя использовать как boolean
boolean flag = true;
// В C/C++ можно, в Java — ОШИБКА:
// if (1) { } // ОШИБКА!
// boolean b = 1; // ОШИБКА!
// int x = true; // ОШИБКА!
// Правильно:
if (flag) { }
if (count > 0) { }
Naming conventions для boolean
// Используйте is/has/can/should для boolean переменных и методов
boolean isReady;
boolean hasChildren;
boolean canEdit;
boolean shouldUpdate;
public boolean isEmpty() { return size == 0; }
public boolean hasNext() { return index < length; }
Литералы
Литерал — это фиксированное значение, записанное в коде.
Целочисленные литералы
// Десятичные (по умолчанию)
int decimal = 42;
// Шестнадцатеричные (0x или 0X)
int hex = 0x2A; // 42
int color = 0xFF00FF;
// Восьмеричные (начинаются с 0)
int octal = 052; // 42
// Двоичные (0b или 0B, Java 7+)
int binary = 0b101010; // 42
// Подчёркивания для читаемости (Java 7+)
int million = 1_000_000;
long creditCard = 1234_5678_9012_3456L;
int bytes = 0b1111_0000_1111_0000;
Литералы с плавающей точкой
double d1 = 3.14;
double d2 = 3.14d; // явный суффикс
double d3 = 314e-2; // научная нотация
double d4 = 0x1.0p3; // hex float: 1.0 × 2³ = 8.0
float f1 = 3.14f; // обязательный суффикс
float f2 = 3.14F;
Символьные литералы
char c1 = 'A';
char c2 = '\n';
char c3 = '\u0041'; // 'A' в Unicode
Логические литералы
boolean t = true;
boolean f = false;
Null литерал
String s = null; // только для ссылочных типов
// int x = null; // ОШИБКА! Примитивы не могут быть null
Значения по умолчанию
Для полей класса примитивы инициализируются автоматически:
public class Defaults {
byte b; // 0
short s; // 0
int i; // 0
long l; // 0L
float f; // 0.0f
double d; // 0.0
char c; // '\u0000' (null character)
boolean z; // false
}
Локальные переменные НЕ инициализируются автоматически:
public void method() {
int x;
// System.out.println(x); // ОШИБКА! x не инициализирована
int y = 0;
System.out.println(y); // OK
}
Преобразования типов
Расширяющее преобразование (автоматическое)
Меньший тип автоматически преобразуется в больший:
byte → short → int → long → float → double
↑
char
int i = 100;
long l = i; // int → long (автоматически)
double d = l; // long → double (автоматически)
char c = 'A';
int code = c; // char → int (автоматически)
Сужающее преобразование (явное)
Требует явное приведение типа. Может привести к потере данных!
double d = 3.99;
int i = (int) d; // 3 (дробная часть отбрасывается)
long big = 1000000000000L;
int small = (int) big; // переполнение!
int value = 130;
byte b = (byte) value; // -126 (переполнение!)
Приведение типов
// Синтаксис: (тип) выражение
int i = (int) 3.14; // 3
byte b = (byte) 300; // 44 (300 % 256)
char c = (char) 65; // 'A'
double d = (double) 5 / 2; // 2.5 (не 2!)
Приведение в выражениях
byte a = 10;
byte b = 20;
// byte c = a + b; // ОШИБКА! a + b даёт int
byte c = (byte) (a + b); // OK
// Операции с byte, short, char всегда дают int
short s1 = 10;
short s2 = 20;
// short s3 = s1 + s2; // ОШИБКА!
int s3 = s1 + s2; // OK
Wrapper-классы
Каждый примитив имеет соответствующий класс-обёртку:
| Примитив | Wrapper |
|---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Autoboxing и Unboxing
Java автоматически преобразует между примитивами и wrapper-классами:
// Autoboxing: примитив → объект
Integer obj = 42; // int → Integer
List<Integer> list = new ArrayList<>();
list.add(10); // int → Integer
// Unboxing: объект → примитив
int value = obj; // Integer → int
int first = list.get(0); // Integer → int
Осторожно с null!
Integer obj = null;
int value = obj; // NullPointerException!
// Безопасная проверка
if (obj != null) {
int safe = obj;
}
Integer cache
Java кэширует Integer объекты для значений -128…127:
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true (один объект из кэша)
Integer c = 1000;
Integer d = 1000;
System.out.println(c == d); // false (разные объекты!)
// Всегда используйте equals() для сравнения объектов
System.out.println(c.equals(d)); // true
Полезные методы
Для числовых типов
// Парсинг строк
int i = Integer.parseInt("42");
double d = Double.parseDouble("3.14");
long l = Long.parseLong("1000000000");
// Конвертация в строку
String s1 = Integer.toString(42);
String s2 = String.valueOf(42); // универсальный способ
// Системы счисления
String binary = Integer.toBinaryString(42); // "101010"
String hex = Integer.toHexString(255); // "ff"
int fromHex = Integer.parseInt("ff", 16); // 255
// Min/Max
int max = Integer.max(10, 20); // 20
int min = Integer.min(10, 20); // 10
// Сравнение
int cmp = Integer.compare(10, 20); // -1 (10 < 20)
Для Character
char c = 'A';
Character.isLetter(c); // true
Character.isDigit('5'); // true
Character.isWhitespace(' '); // true
Character.isUpperCase(c); // true
Character.toLowerCase(c); // 'a'
Character.toUpperCase('b'); // 'B'
Итоги
Вы изучили 8 примитивных типов Java:
Целочисленные:
byte(1 байт) — редко используетсяshort(2 байта) — редко используетсяint(4 байта) — основной целочисленный типlong(8 байт) — для больших чисел, суффиксL
С плавающей точкой:
float(4 байта) — суффиксf, низкая точностьdouble(8 байт) — основной дробный тип
Другие:
char(2 байта) — Unicode символboolean(~1 бит) — true/false
Ключевые моменты:
- Используйте
intиdoubleпо умолчанию - Не забывайте суффиксы
Lдля long иfдля float - Избегайте
floatдля финансовых расчётов (используйтеBigDecimal) char— это число 0-65535, не может хранить emoji напрямуюbooleanне конвертируется в число и обратно- Осторожно с Integer cache при сравнении объектов через
==
Задания для практики
-
Объявите переменные всех 8 примитивных типов и выведите их значения
-
Напишите программу, которая демонстрирует переполнение
intпри умножении больших чисел -
Сравните результат
0.1 + 0.2с0.3и объясните, почему они не равны -
Напишите метод, который определяет, является ли символ цифрой, без использования
Character.isDigit() -
Продемонстрируйте разницу между
Integer.valueOf(100) == Integer.valueOf(100)иInteger.valueOf(1000) == Integer.valueOf(1000)