Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Примитивные типы данных

byte, short, int, long, float, double, boolean, char

Материалы

ТипСсылка
ДокументPrimitive Data Types
ВидеоJava Data Types

Java — строго типизированный язык. Каждая переменная должна иметь объявленный тип. В этом разделе мы изучим 8 примитивных типов данных — фундамент Java.

Обзор примитивных типов

Java имеет ровно 8 примитивных типов:

ТипРазмерДиапазон значенийЗначение по умолчанию
byte1 байт-128 … 1270
short2 байта-32 768 … 32 7670
int4 байта-2 147 483 648 … 2 147 483 6470
long8 байт-9 223 372 036 854 775 808 … 9 223 372 036 854 775 8070L
float4 байта~±3.4×10^38 (6-7 значащих цифр)0.0f
double8 байт~±1.7×10^308 (15-17 значащих цифр)0.0
char2 байта0 … 65 535 (Unicode)‘\u0000’
boolean~1 битtrue / falsefalse

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

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Возврат каретки
\\Обратный слэш
\'Одинарная кавычка
\"Двойная кавычка
\uXXXXUnicode символ (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
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

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 при сравнении объектов через ==

Задания для практики

  1. Объявите переменные всех 8 примитивных типов и выведите их значения

  2. Напишите программу, которая демонстрирует переполнение int при умножении больших чисел

  3. Сравните результат 0.1 + 0.2 с 0.3 и объясните, почему они не равны

  4. Напишите метод, который определяет, является ли символ цифрой, без использования Character.isDigit()

  5. Продемонстрируйте разницу между Integer.valueOf(100) == Integer.valueOf(100) и Integer.valueOf(1000) == Integer.valueOf(1000)