Что такое знаковые (signed) целочисленные типы в Java?

Ответ

Знаковые (signed) типы — это примитивные целочисленные типы в Java, которые используют старший бит (знаковый бит) для хранения знака числа: 0 для положительных чисел и 1 для отрицательных. Остальные биты хранят абсолютное значение в дополнительном коде (two's complement).

Список знаковых типов в Java:

Тип Размер Диапазон
byte 8 бит от -128 до 127
short 16 бит от -32 768 до 32 767
int 32 бит от -2³¹ (-2 147 483 648) до 2³¹-1 (2 147 483 647)
long 64 бит от -2⁶³ до 2⁶³-1

Пример и важные следствия:

int positive = 42;    // Бинарно: 00101010
int negative = -42;   // Бинарно: 11010110 (дополнительный код от 42)

Практическое значение:

  1. Арифметические операции работают с учетом знака (деление, сдвиг вправо >>).
  2. Беззнаковые (unsigned) операции требуют специальных методов:
    int a = -1;
    // Сравнение как беззнаковое (unsigned compare)
    int result = Integer.compareUnsigned(a, 200); // -1 > 200 при беззнаковой интерпретации
    // Преобразование в беззнаковую строку
    String unsignedString = Integer.toUnsignedString(a); // "4294967295"
  3. Сдвиг вправо без учета знака выполняется оператором >>>, который заполняет старшие биты нулями.

Ответ 18+ 🔞

А, ну вот, опять эти ваши знаковые типы, блядь! Сидишь, такой, думаешь: "Ну, числа и числа, чё тут такого?" А нихуя! Тут целая подстава, ёпта!

Смотри, есть у нас в Java такие примитивные целочисленные типы: byte, short, int, long. И все они, сука, знаковые (signed). Это значит, что самый левый, старший бит — он не простой, он у нас знаковый, хитрая жопа! Если там нолик — число положительное, всё пучком. Если единичка — всё, пиздец, минус, готовь очко.

Остальные биты уже само значение хранят, да ещё и в дополнительном коде (two's complement), чтобы удобнее было отрицательные считать. Короче, магия, но магия стандартная.

Вот тебе табличка, чтобы не ебал мозг:

Тип Размер (в битах) Диапазон (от и до, с минусом, блядь!)
byte 8 от -128 до 127
short 16 от -32 768 до 32 767
int 32 от -2 147 483 648 до 2 147 483 647
long 64 от какого-то овердохуища минусового до такого же плюсового, но на единичку меньше

Примерчик, чтобы въехать:

int positive = 42;    // В битах: 00101010. Нолик в начале — всё ок.
int negative = -42;   // А тут уже пиздец: 11010110. Это доп. код от 42, единичка в начале — минус.

А теперь, блядь, самое важное, где все и обоссываются:

  1. Все обычные операции — они ЗНАКОВЫЕ. Делишь, умножаешь, сдвигаешь вправо (>>) — Java помнит про этот чёртов знаковый бит. Сдвинешь отрицательное >> — слева единички подтянутся, потому что "минус же, нахуй!"

  2. Хочешь работать как с беззнаковым (unsigned)? А нихуя так просто! Придётся использовать специальные методы из коробки, типа Integer.compareUnsigned() или Integer.toUnsignedString(). Смотри, какой пиздец:

    int a = -1; // В знаковом мире это -1, да.
    // А давай сравним его с 200, как будто они оба беззнаковые?
    int result = Integer.compareUnsigned(a, 200); // Удивление пиздец! Окажется, что -1 БОЛЬШЕ 200, потому что в беззнаковом мире это 4 миллиарда с хвостиком!
    // Или превратим минус единицу в строку без знака:
    String unsignedString = Integer.toUnsignedString(a); // Получим "4294967295"! Вот тебе и -1!
  3. Сдвиг вправо БЕЗ знака — это отдельная операция >>>. Этот оператор, сука, неумолим: он тупо сдвигает биты вправо, а освободившиеся слева места заполняет НУЛЯМИ. Не важно, минус там был или плюс. Просто нули. Хуй с горы, короче.

Вот так-то. Выглядит как мелочь, а потом бац — и ты уже неделю дебажишь, почему твой битовый флаг нахуй сломался. Потому что забыл, что byte у тебя от -128 до 127, а не от 0 до 255, мудя!