Poniżej znajduje się prosta aplikacja, która rzutuje jedną liczbę między różnymi typami, tak że na wejściu mamy typ int
, na wyjściu także.
1 2 3 4 5 |
I pytanie, co zostanie wydrukowane?.
Program jest dosyć prosty. Konwersja rozpoczyna się od cyfry -1, będącej typu int
(domyślny typ dla liczb całkowitych). Następnie zostaje dokonana konwersja zawężająca do typu byte
(8 bitów), potem do char
(16 bitów) a na końcu z powrotem do typu int
(32 bity). A na końcu drukuje liczbę 65535. I teraz pytanie brzmi, dlaczego nie -1?
Java wykorzystuje do prowadzenia obliczeń tzw. kod uzupełnień do dwóch:
Kod uzupełnień do dwóch (w skrócie U2 lub ZU2) – system reprezentacji liczb całkowitych w dwójkowym systemie pozycyjnym. Jest obecnie najpopularniejszym sposobem zapisu liczb całkowitych w systemach cyfrowych. Jego popularność wynika z faktu, że operacje dodawania i odejmowania są w nim wykonywane tak samo jak dla liczb binarnych bez znaku.
Z tej reprezentacji wynika, że liczba -1 w reprezentacji dwójkowej składa się z 32 jedynek. Rzutowanie z typu int
to typu byte
jest prosta i nie sprawia problemów. W wyniku tej konwersji zostają usunięte wszystkie bity oprócz tych najmniej znaczących. Czyli koniec końców także otrzymujemy liczbę -1 zapisane w 8 bitach (8 jedynek).
Natomiast rzutowanie na tym char
sprawia więcej problemów. Typ char
jest typem, w kŧórym można zapisać tylko liczby dodatnie, więc nie można zapisać w nim wartości ujemnej. Z tego powodu konwersja z typu char
do byte
nie jest uważana za konwersję rozszerzającą, tylko jest konwersja zawężająca. To powoduje, że najpierw nasŧępuje niejawna konwersja do typu int
a dopiero teraz do typu char
.
Więc najpierw następuje konwersja z typu byte
na int
, co powoduje, że uzyskujemy liczbę -1, która w zapisie dwójkowym składa się z 32 jedynek. Następnie dokonana zostaje konwersja do typu char
, czyli zostają zachowane najmniej znaczące 16 bitów, czyli same jedynki czyli 65535.