8 maja 2008

SCJP – Literały

Literały (ang. literals) to pierwsze zagadnienie z trzeciego rozdziału streszczanej książki "SCJP Sun Certified Programmer for Java 5 Study Guide (Exam 310-055)", aczkolwiek dla opracowania dzisiejszego artykułu korzystałem ze specyfikacji języka – książka jest tutaj jak dla mnie daleko za mało precyzyjna. Więcej informacji w artykule "Przygotowania do SCJP czas zacząć".

Literał to wartość wpisana bezpośrednio w kodzie źródłowym programu. W języku Java wyróżniamy 6 różnych typów literałów, są to literały liczbowe całkowite i zmiennopozycyjne, literały logiczne, znakowe, napisowe i literał null.

Literały liczbowe całkowite (ang. integer literals) mogą być wyrażone jako liczby dziesiętne, szesnastkowe i ósemkowe. Literały szesnastkowe oznaczamy przedrostkiem 0x lub 0X, po czym następuje liczba szesnastkowa, tzn. dowolny ciąg cyfr od 0 do 9 i liter od a/A do f/F. Dopuszczalne jest dowolne mieszanie liter dużych i małych. Liczba może mieć także dowolną ilość zer początkowych, co naturalnie nie wpływa na jej wartość. Zer początkowych nie może mieć natomiast liczba dziesiętna, ponieważ umieszczenie zera na początku liczby oznacza, że jest to liczba ósemkowa. Liczbę ósemkową oznaczamy właśnie w ten sposób, że umieszczamy cyfrę 0 jako przedrostek. Zer tych może być dowolnie wiele. Naturalnie cyfry ósemkowe to cyfry z zakresu od 0 do 7. Przykładowe literały dziesiętne to: 123, 0, 9809238, literały ósemkowe to: 0123, 00, 0000077143 a szesnastkowe: 0xABC, 0X123, 0xAbCd, 0X1A2b, 0x0, 0x00001. Egzamin na SCJP co prawda nie wymaga od nas biegłości w posługiwaniu się innymi niż dziesiętny systemami liczbowymi, ale warto wiedzieć, że literały szesnastkowe i ósemkowe mogą reprezentować liczby ujemne, np. literał 0x80000000 reprezentuje wartość -2147483648, zatem wyrażenie -0x80000000 reprezentuje wartość dodatnią 2147483648.

Domyślnie literały całkowite są typu ‘int’. Literały typu ‘long’ otrzymujemy poprzez dodanie sufixu L lub l. Literały 123 czy 0xAbCd są więc typu ‘int’ a literały 123L czy 0xAbCdl typu ‘long’. Ze względu na podobieństwo małej litery l do cyfry 1 proponuje się używanie tylko dużej litery L.

Literały liczbowe zmiennopozycyjne mogą być wyrażone jako liczby dziesiętne i szesnastkowe. Ogólnie, literały liczbowe zmiennopozycyjne składają się kolejno z części całkowitej, kropki, części ułamkowej, symbolu wykładnika i wartości wykładnika oraz litery oznaczającej typ. Uf, dużo tego i brzmi nużąco mądrze, a do tego to jeszcze nie koniec, ale trzeba się jakoś przegryźć. Wszystkie literały zmiennopozycyjne są domyślnie typu ‘double’. Literały typu ‘float’ oznaczamy poprzez dodanie na końcu litery F lub f. Możemy także explicite oznaczyć, że liczba jest typu ‘double’ dodając literę D lub d. Litera oznaczająca typ to zatem jedna z liter: F, f, D, d.

Jeśli chodzi o dziesiętne literały zmiennopozycyjne, to wszystkie składowe są opcjonalne, przy czy musi być obecne, co najmniej jedno z dwojga: część całkowita albo ułamkowa, oraz jedno z trojga: kropka albo symbol i wartość wykładnika albo litera oznaczająca typ. Część całkowita i ułamkowa to dziesiętne liczby naturalne. Symbol wykładnika to litera E lub e. Wartość wykładnika to dziesiętna liczba całkowita, dodatnia lub ujemna. Przykładowe, poprawne dziesiętne literały zmiennopozycyjne to zatem: 0D, 1.F, 123., .3450, 23e1f, 1e1, 3.0E-1F.

Literały zmiennopozycyjne szesnastkowe obowiązują inne reguły. Obowiązkową częścią jest symbol i wartość wykładnika, przy czym symbol wykładnika to litera P lub p. Obowiązkowa jest też – analogicznie jak dla systemu dziesiętnego – część całkowita albo ułamkowa. Pozostałe części są opcjonalne. Część całkowita zapisana być musi jako liczba szesnastkowa, a więc z prefixem 0X lub 0x. Przykładowe, poprawne szesnastkowe literały zmiennopozycyjne to: 0x3p1, 0x2.3p0f, 0x.1p4d, 0xab.cdp0d. Nie wiedzieć czemu ktoś miałby chcieć zapisywać liczby w takich postaciach, ale język Java to umożliwia a egzaminatorzy na SCJP mogą się o tę wiedzę upomnieć.

Literały logiczne to jeden z dwojga literałów: true albo false. Literały te są typu ‘boolean’ i są to jedyne wartości, które może przyjmować zmienna tego typu. Inaczej niż np. w języku C++, literały 0 czy 1 nie mogą być użyte jako wartości logiczne. Ale temat konwersji typów to nieco inna historia, póki co odłożona na później.

Literały znakowe to pewna reprezentacja pojedynczego znaku ujęta w apostrofy. Znaki mogą być reprezentowane wprost – np. litera a, symbol %, czy cyfra 1 –, w postaci kodu UTF-16 poprzedzonego prefixem \u – czyli od \u0000 do \uffff (albo \uFFFF) – albo jako sekwencje specjalne, tj. \t, \n, \r, \\, \’. Od tego co napisałem obowiązują jeszcze dwa wyjątki – nie można znaków reprezentować poprzez sekwencje \u000a ani \u000d. Odpowiadają one kolejno sekwencjom \n i \r i są niedopuszczalne ze względu na konstrukcję procesu kompilacji. Szczęśliwie w szczegóły nie potrzebujemy wnikać. Przykładowe literały znakowe to: ‘a’, ‘H’, ‘*’, ‘\u1234’, ‘\n’. Literały znakowe są zawsze typu ‘char’.

Literały napisowe to ujęty w cudzysłowy dowolny ciąg znaków, reprezentowanych – z małym wyjątkiem – w taki sam sposób jak dla literałów znakowych. Tym małym wyjątkiem jest, że w literałach napisowych można explicite umieścić znak apostrofu ‘ a nie można umieścić znaku cudzysłowu ", tak więc nie musimy – choć możemy – używać sekwencji \’ a z kolei musimy pisać \" zamiast ".

1 komentarz:

Anonimowy pisze...

Aha! Mamy jeszcze literały specjalne klas (ang. "class literal") dzięki refleksji. W javie klasa też jest objektem!

Można:

Object o = Number.class;
Object o = String.class;

a nawet:

Object o = int.class;

Literałowi klasy X odpowiada sygnatura Class<X>, można więc:

Class<X> = X.class;

dla typów prostych mamy:

Class<Integer> c = int.class;