Jaka jest semantyka języka Java w przypadku liczby ze zmianą znaczenia w literale znakowym, np. „\ 15”?

85

Proszę wyjaśnić, co dokładnie dzieje się, gdy wykonywane są następujące sekcje kodu:

int a='\15';
System.out.println(a);

to wypisuje 13;

int a='\25';
System.out.println(a);

to wypisuje 21;

int a='\100';
System.out.println(a);

to wypisuje 64.

VAr
źródło
22
Wygląda na to, że interpretuje liczbę jako ósemkową.
Nikhil
5
int a='\15'najpierw tworzy na charpodstawie liczby ósemkowej „15” (13 dziesiętnie, jako znak, jest to ascii „Powrót karetki”), którą następnie przekształcasz na intliczbę całkowitą. Jest to legalne, ponieważ znaki są 16-bitowymi liczbami całkowitymi, więc jest to bezpieczna aktualizacja i Java nie wydaje żadnych powiadomień o przesyłaniu. Inne odpowiedzi obejmują już całą rzecz ósemkową / dziesiętną.
Mike 'Pomax' Kamermans

Odpowiedzi:

116

Przypisałeś literał znakowy, który jest oddzielony pojedynczymi cudzysłowami, np. 'a'(W odróżnieniu od literału String, który jest oddzielony podwójnymi cudzysłowami, np. "a") Do intzmiennej. Java automatycznie poszerza rzutowanie z 16-bitowego bez znaku chardo 32-bitowego ze znakiem int.

Jednak gdy literał znakowy jest odwrotnym ukośnikiem, po którym następują 1-3 cyfry, jest to ósemkowa ( podstawa / podstawa 8) reprezentacja znaku. A zatem:

  • \15= 1 × 8 + 5 = 13 (powrót karetki; tak samo jak '\r')
  • \25 = 2 × 8 + 5 = 21 (znak NAK - negatywne potwierdzenie)
  • \100= 1 × 64 + 0 × 8 + 0 = 64 (symbol @; to samo co '@')

Aby uzyskać więcej informacji na temat literałów znaków i sekwencji ucieczki, zobacz sekcje JLS:

Cytując BNF z 3.10.6:

OctalEscape:
    \ OctalDigit
    \ OctalDigit OctalDigit
    \ ZeroToThree OctalDigit OctalDigit

OctalDigit: one of
    0 1 2 3 4 5 6 7

ZeroToThree: one of
    0 1 2 3
Czeski
źródło
3
Nie mogę go znaleźć w sekcji 3.10.1. Jest w 3.10.4, Literały postaci
Rafi Kamal
1
Sekcja poświęcona literałom całkowitym jest nieistotna. Patrz sekcja 3.10.4 . Zobacz także sekcję 3.10.6, aby poznać sekwencje specjalne znaków i łańcuchów.
Ted Hopp
1-3 digits- powinno być 0-3. A jeśli chodzi o 3-cyfrowy ósemkowy, dwucyfrowy ósemkowy nadal może mieć od 0-7. dawny. „\ 77” jest nadal ważny.
Jayamohan
6
@Jayamohan Miałem na myśli 1-3 pod względem ilości, a nie wartości
Bohemian
@Czech. Niezła odpowiedź. Proponuję dodać tutaj składnię ósemkowego literału ucieczki, aby była bardziej przejrzysta. :)
Rohit Jain
19

Notacja \nnnoznacza ósemkowy kod znaku w Javie. więc int a = '\15'przypisuje automatycznie rzucaną wartość znaku ósemkowego 15, do aktórego jest dziesiętnie 13.

Bahman Movaqar
źródło
5
Zapis \nnnma nie oznaczają liczbę ósemkową w Javie. W kodzie OP oznacza ósemkową sekwencję ucieczki znaków. Otaczające cudzysłowy są niezbędne. Znak jest następnie rozszerzany do wartości całkowitej przez przypisanie. (Liczby ósemkowe są oznaczone początkową cyfrą zerową).
Ted Hopp
Słuszna uwaga; Powinienem wspomnieć o automatycznej obsadzie w odpowiedzi. Zaktualizowałem odpowiedź.
Bahman Movaqar
6

Fakt, że cyfry umieściłeś w cudzysłowie, każe podejrzewać, że interpretuje to liczbę jako literał znakowy. Kolejne cyfry muszą być zapisane ósemkowo.

Nikhil
źródło