Відповідь - доповнення двох .
Коротше кажучи, Java (і більшість сучасних мов) не представляють цілі числа зі знаком, використовуючи представлення знакової величини. Іншими словами, 8-бітове ціле число не є знаковим бітом, за яким слідує 7-бітове ціле без знака.
Натомість цілі від’ємні числа представлені в системі, яка називається доповненням двох, що дозволяє простіше арифметичну обробку в апаратному забезпеченні, а також усуває потенційну неоднозначність наявності позитивного нуля та від’ємного нуля. Побічним ефектом усунення від’ємного нуля є те, що внизу діапазону завжди є одне зайве від’ємне число.
Ще однією цікавою властивістю двох комплементарних систем є те, що перший біт ефективно діє як знаковий індикатор (тобто всі числа, що починаються з біта 1, є від’ємними), але наступні сім бітів не слід інтерпретувати самостійно як число без знака для до якого застосовується знаковий біт.
Доповнення двох не дуже складно, але отримання початкового хорошого уявлення про те, що таке доповнення двох, і як і чому воно працює, ймовірно, виходить за рамки відповіді SO. Почніть зі статті у Вікіпедії або пошукайте в Google термін, щоб отримати більше ресурсів.
Щоб спробувати коротко звернутися до вашого запиту про -128, основна ідея створення додаткового числа двох полягає у прийнятті беззнакової форми числа, інвертуванні всіх бітів та додаванні одного. Отже, непідписаний 128 - це 10000000. Перевернуте, це 01111111, і додавання одного отримує 10000000 знову. Отже, у системі доповнення двох, 10000000 однозначно становить -128, а не +128. Числа, що перевищують або дорівнюють +128, просто не можуть бути представлені у 8 бітах за допомогою системи доповнення двох, оскільки вони будуть неоднозначними з формами від'ємних чисел.