Типы данных в Java
Java различает примитивные типы и ссылочные типы. Примитивных всего восемь: byte, short, int, long, float, double, char, boolean. Их значения хранятся прямо в переменной — без обёрток и заголовков объекта. Всё остальное (String, массивы, любые ваши классы) — ссылочные типы: переменная хранит адрес объекта в куче.
Размер примитива одинаков на всех платформах — это принципиальное отличие от C/C++. int в Java всегда 32 бита, long всегда 64 бита, независимо от ОС и процессора.
Каждому примитиву соответствует класс-обёртка (Integer, Double, Boolean…) — он нужен, когда требуется объект: в коллекциях List<Integer>, при работе с дженериками, для null-значения.
Зачем это нужно
Правильно выбирать тип под задачу:
byteдля пина (0..127),intдля счётчика,longдля миллисекунд эпохи,doubleдля расчётов.Избегать переполнения и потери точности.
Понимать разницу между «значение» (примитив) и «ссылка» (объект) — это основа поведения присваивания и передачи в методы.
Пример 1. Все восемь примитивов
public class Primitives {
public static void main(String[] args) {
byte b = 100; // 8 бит, -128..127
short s = 30000; // 16 бит, -32 768..32 767
int i = 2_000_000_000; // 32 бита
long l = 9_000_000_000L; // 64 бита, суффикс L
float f = 3.14f; // 32 бита, суффикс f
double d = 3.141592653589793; // 64 бита
char c = 'Z'; // 16 бит, Unicode
boolean flag = true;
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(c);
System.out.println(flag);
}
}
Вывод:
100
30000
2000000000
9000000000
3.14
3.141592653589793
Z
true
Пример 2. Диапазоны значений
public class Ranges {
public static void main(String[] args) {
System.out.println("byte: " + Byte.MIN_VALUE + " .. " + Byte.MAX_VALUE);
System.out.println("short: " + Short.MIN_VALUE + " .. " + Short.MAX_VALUE);
System.out.println("int: " + Integer.MIN_VALUE + " .. " + Integer.MAX_VALUE);
System.out.println("long: " + Long.MIN_VALUE + " .. " + Long.MAX_VALUE);
System.out.println("float ~ 7 знач. цифр, double ~ 15-16.");
}
}
Вывод:
byte: -128 .. 127
short: -32768 .. 32767
int: -2147483648 .. 2147483647
long: -9223372036854775808 .. 9223372036854775807
float ~ 7 знач. цифр, double ~ 15-16.
Пример 3. Значения по умолчанию у полей
public class Defaults {
static byte b;
static short s;
static int i;
static long l;
static float f;
static double d;
static char c;
static boolean flag;
static String text;
public static void main(String[] args) {
System.out.println("byte = " + b);
System.out.println("short = " + s);
System.out.println("int = " + i);
System.out.println("long = " + l);
System.out.println("float = " + f);
System.out.println("double = " + d);
System.out.println("char = [" + c + "] (код " + (int) c + ")");
System.out.println("boolean = " + flag);
System.out.println("String = " + text);
}
}
Вывод:
byte = 0
short = 0
int = 0
long = 0
float = 0.0
double = 0.0
char = [ ] (код 0)
boolean = false
String = null
Поля класса автоматически получают значение по умолчанию. Локальные переменные — нет, их нужно явно инициализировать.
Пример 4. Неявное и явное приведение
public class Casting {
public static void main(String[] args) {
int i = 100;
long l = i; // неявное расширение int -> long
double d = l; // неявное long -> double
System.out.println(l + " " + d);
double pi = 3.99;
int truncated = (int) pi; // явное сужение, отбрасывает дробную часть
System.out.println(truncated);
int big = 130;
byte b = (byte) big; // выход за диапазон byte: -128..127
System.out.println(b);
}
}
Вывод:
100 100.0
3
-126
Расширение (от меньшего к большему) — автоматическое. Сужение требует явного (тип) и может потерять данные.
Пример 5. char как число
public class CharAsNumber {
public static void main(String[] args) {
char a = 'A';
int code = a; // 65
char next = (char) (a + 1); // 'B'
System.out.println(a + " -> " + code);
System.out.println(next);
for (char ch = 'A'; ch <= 'E'; ch++) {
System.out.print(ch);
}
System.out.println();
}
}
Вывод:
A -> 65
B
ABCDE
char — это беззнаковое 16-битное число (Unicode code unit). Над ним работают арифметические операции.
Пример 6. Обёртки и автоупаковка
import java.util.ArrayList;
import java.util.List;
public class Wrappers {
public static void main(String[] args) {
Integer x = 42; // автоупаковка: int -> Integer
int y = x; // авторапаковка: Integer -> int
List<Integer> pins = new ArrayList<>();
pins.add(13);
pins.add(12);
pins.add(11);
int sum = 0;
for (Integer pin : pins) {
sum += pin; // авторапаковка
}
System.out.println("Сумма пинов: " + sum);
System.out.println("MAX_VALUE: " + Integer.MAX_VALUE);
}
}
Вывод:
Сумма пинов: 36
MAX_VALUE: 2147483647
Коллекции работают только с объектами, поэтому List<int> запрещён — используют List<Integer>.
Пример 7. Переполнение целых
public class Overflow {
public static void main(String[] args) {
int max = Integer.MAX_VALUE;
int overflow = max + 1;
System.out.println("max = " + max);
System.out.println("max + 1 = " + overflow);
// Решение: использовать long
long safe = (long) max + 1;
System.out.println("safe long = " + safe);
}
}
Вывод:
max = 2147483647
max + 1 = -2147483648
safe long = 2147483648
При переполнении Java не выбрасывает исключение — значение «закольцовывается». Будьте внимательны при умножении больших int.
Пример 8. String — ссылочный тип
public class StringIsReference {
public static void main(String[] args) {
String a = "AlashEd";
String b = a; // b ссылается на ту же строку
String c = new String("AlashEd");
System.out.println(a.equals(b)); // true — содержимое
System.out.println(a.equals(c)); // true — содержимое
System.out.println(a == b); // true — одна ссылка (литералы кешируются)
System.out.println(a == c); // false — new String — отдельный объект
}
}
Вывод:
true
true
true
false
Для сравнения строк по содержимому всегда используйте equals, а не ==.
Подводные камни
Предупреждение
double не точен:
0.1 + 0.2 == 0.3вернётfalse. Для денег —BigDecimal.Сужающее приведение молча обрезает:
(byte) 200даст-56, без предупреждения в рантайме.Integer кешируется только в диапазоне -128..127:
Integer.valueOf(200) == Integer.valueOf(200)вернётfalse. Сравнивайте объекты черезequals.null в обёртке + авторапаковка → NullPointerException:
Integer x = null; int y = x;— упадёт в рантайме.Java не имеет беззнакового int: для 32-битных беззнаковых используйте
Integer.toUnsignedLongили работайте сlong.char != строка:
"A"— этоString,'A'— этоchar.System.out.println("A" + 1)даст"A1", аSystem.out.println('A' + 1)даст66.
См. также
Hello World на Java — первая программа на Java
Комментарии в Java — комментарии
Переменные и литералы — переменные и литералы
Операторы в Java — операторы
Примечание
Лицензия и источники
Техническое описание адаптировано из официальной документации Oracle Java Tutorials (https://docs.oracle.com/javase/tutorial/), Oracle Free Documentation License. Перевод на русский, примеры и пояснения — © AlashEd Wiki.