Откуда берутся минимальное и максимальное значения int?

Минимальное и максимальное значения типа int в Java определяются исходя из размера и способа представления данных в памяти. Тип int в Java является примитивным типом, который занимает 4 байта (32 бита) и представляет собой знаковое целое число, используя дополнительный код (two's complement) для хранения отрицательных значений.

Бинарное представление int и диапазон значений

Тип int в Java имеет строго определённый размер:

  • Размер: 32 бита (4 байта)

  • Представление: знаковое, с использованием **дополнительного кода (two’s complement)
    **

Дополнительный код — это система, в которой:

  • самый старший бит (левый, старший) является знаковым битом:

    • 0 — положительное число,

    • 1 — отрицательное.

  • диапазон значений асимметричен: на одно отрицательное число больше, чем положительных.

Расчёт диапазона значений

Общий диапазон для 32-битного знакового целого числа:

  • Минимальное значение: -2^31 = -2,147,483,648

  • Максимальное значение: 2^31 - 1 = 2,147,483,647

Таким образом:

public static final int MIN_VALUE = -2147483648;
public static final int MAX_VALUE = 2147483647;
Они доступны в классе-обёртке java.lang.Integer как **константы**:
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Integer.MAX_VALUE); // 2147483647

Почему максимальное значение меньше по модулю, чем минимальное?

Это связано с тем, что:

  • Всего возможно представить 2^32 = 4,294,967,296 различных комбинаций битов.

  • Из-за наличия знака, половина этих комбинаций (2^31) отводится под отрицательные значения, одна — под ноль, и оставшиеся — под положительные значения.

Поскольку 0 считается неотрицательным, то:

  • Отрицательных чисел: 2^31 (включая -2^31)

  • Положительных: 2^31 - 1 (от 1 до 2^31 - 1)

  • 0 занимает отдельную ячейку в положительной части

Таким образом, отрицательных значений на одно больше, чем положительных.

Бинарный пример

  • int в Java — 32-битное значение:

Примеры:

  • 0 в двоичном виде: 00000000 00000000 00000000 00000000

  • 1: 00000000 00000000 00000000 00000001

  • -1: 11111111 11111111 11111111 11111111

  • Integer.MAX_VALUE: 01111111 11111111 11111111 11111111 = 2,147,483,647

  • Integer.MIN_VALUE: 10000000 00000000 00000000 00000000 = -2,147,483,648

При попытке выйти за пределы этого диапазона произойдёт переполнение (overflow):

int max = Integer.MAX_VALUE;
System.out.println(max + 1); // Вывод: -2147483648 (переполнение)
int min = Integer.MIN_VALUE;
System.out.println(min - 1); // Вывод: 2147483647 (переполнение)

Это объясняется тем, что Java не генерирует исключений при переполнении целочисленных типов. Числа "переворачиваются" по кругу в пределах 32-битной области.

Как JVM обрабатывает int на уровне байтов

На уровне байт, int занимает 4 байта и хранится в двухкомплементарной форме, которая является стандартом для большинства современных процессоров и языков программирования.

Пример:

int a = -1;
Значение a в памяти будет: 0xFFFFFFFF, то есть каждый бит равен 1.

Для Integer.MIN_VALUE (-2147483648) это будет:

10000000 00000000 00000000 00000000

Для Integer.MAX_VALUE (2147483647) это будет:

01111111 11111111 11111111 11111111

Почему используется дополнительный код

Дополнительный код (two's complement) выбран в качестве стандарта представления целых чисел в Java (и в большинстве языков) по следующим причинам:

  1. Одна уникальная нулевая комбинация: 0x00000000, а не две (как в знако-величинной форме).

  2. Арифметические операции одинаковы как для положительных, так и для отрицательных чисел — не требуется специальная логика.

  3. Упрощённая реализация на уровне процессора.

  4. Возможность сравнения знаков по старшему биту.

Связь с другими типами

Аналогичным образом рассчитываются минимальные и максимальные значения других примитивных типов в Java:

Тип Размер Мин. значение Макс. значение
byte 8 бит -2^7 = -128 2^7 - 1 = 127
--- --- --- ---
short 16 бит -2^15 = -32,768 2^15 - 1 = 32,767
--- --- --- ---
int 32 бит -2^31 = -2,147,483,648 2^31 - 1 = 2,147,483,647
--- --- --- ---
long 64 бит -2^63 2^63 - 1
--- --- --- ---

Все знаковые типы используют дополнительный код.

Где хранятся MIN_VALUE и MAX_VALUE

Они определены в классе-обёртке java.lang.Integer как публичные статические финальные константы:

public final class Integer extends Number implements Comparable<Integer> {
public static final int MIN_VALUE = 0x80000000; // -2147483648
public static final int MAX_VALUE = 0x7fffffff; // 2147483647
...
}

Значения записаны в шестнадцатеричном виде:

- 0x80000000 = 10000000 00000000 00000000 00000000 (32 бита)    
- 0x7FFFFFFF = 01111111 11111111 11111111 11111111 (32 бита)  

Эти значения не меняются и доступны в любом месте программы как:

int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE;

Они также применяются при проверках на переполнение, при сериализации, генерации диапазонов и других числовых операциях.