1 Wybrane elementy języka JavaPaweł Zdziarski
2 Wyjątki Reflection Tworzenie i zarządzanie obiektamiGarbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
3 Wyjątki Obsługa błędów semantycznych (runtime) w sposób efektywniejszy niż zwracanie kodu błędu metody Podnoszenie wyjątku Wywołanie metody podnoszącej wyjątek (throws) Explicite: klauzulą throw
4 Obsługa wyjątków Wyjątki są zgodnie z definicją języka precise – zoptymalizowana implementacja może wykonać część instrukcji naprzód, ale w przypadku zgłoszenia wyjątku musi zadbać o to, żeby w widocznym stanie wykonania (user-visible state) wyliczone były dokładnie te wyrażenia, które wystąpiły przed wyrażeniem podnoszącym wyjątek Znajdowana jest klauzula catch bloku try-catch dynamicznie zawierającego generujące wyjątek wyrażenie
5 Obsługa wyjątków Jaki będzie rezultat wykonania try{try { throw new Exception1(); } catch(Exception1 e){ System.out.println("Wewnetrzny catch: ” +e.toString()); throw new Exception2(); } finally {throw new Exception3();} }catch (Exception e) {System.out.println("Zewnetrzny catch: ” +e.toString());} Blok try-catch-finally ma jeden atrybut – propagowany dalej wyjątek. Zgodnie z definicją języka, wewnętrzny blok w tym przykładzie będzie propagował wyjątek klasy Exception3, a więc Wewnetrzny catch: mypackage18.Application1$Exception1 Zewnetrzny catch: mypackage18.Application1$Exception3
6 Przyczyny powstania wyjątkuBłąd wykonania JVM – wyjątek zgłaszany synchronicznie Operacja niezgodna z semantyką języka (np. java.lang.ArithmeticException ) Błąd ładowania/linkowania programu ( NoClassDefFound ) Brak zasobu ( OutOfMemoryError, NoRouteToHostException ) Jawne użycie klauzuli throw Wyjątek podnoszony asynchronicznie Może wystąpić potencjalnie w dowolnym punkcie wykonania bieżącego wątku Inny wątek wywołuje stop() Wewnętrzny błąd JVM ( VirtualMachineError )
7 Hierarchia wyjątków checked (podklasy Exception nie będące RuntimeException) – muszą być wyspecyfikowane w klauzuli throws metody lub konstruktora; kompilator wymusza implementowanie obsługi takich wyjątków Unchecked – kompilator nie wymusza na programiście obsługi (ani deklaracji throws) RuntimeException (np. ArithmeticException, NullPointerException) - kompilator nie ma możliwości posłużenia się zaawansowanymi technikami dowodzenia poprawności programów i nie może przez to stwierdzić, czy dany ciąg instrukcji może wygenerować taki wyjątek lub nie Error (np. OutOfMemoryError extends VirtualMachineError) – mamy do czynienia z „nienormalnym” (abnormal) stanem JVM
8 Error jest osobną, dziedziczącą po Throwable klasą – dzięki temu wszystkie wyjątki, które da się jakoś obsłużyć, można „potraktować” konstrukcją catch (Exception e)
9 Reflection Wyjątki Tworzenie i zarządzanie obiektamiGarbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
10 Pakiet java.lang.reflectDostęp do obiektów reprezentujących konstrukcje samego języka Obiekt Class (pakiet java.lang) reprezentuje załadowaną postać binarną klasy; użycie: public static Class forName(String className) throws ClassNotFoundException Method reprezentuje metodę klasy lub interfejsu Class c = Class.forName(nazwaKlasy); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i].toString()); Analogiczne użycie obiektów klas Field, Constructor Interfejs Member implementowany przez Field, Constructor, Class i Method; udostępnia metodę getModifiers()
11 Tworzenie i zarządzanie obiektamiWyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
12 Konstruktory W kodzie konstruktora pierwsza instrukcja może, opcjonalnie, być explicite wywołaniem konstruktora. Wpp domyślnie super() jest pierwszą instrukcją kodu konstruktora Explicite wywołania konstruktora this(
13 Wyrazenie.super() Tzw. kwalifikowane wywołanie konstruktora nadklasy. Przykład ze specyfikacji języka: class Outer { class Inner{ } } class ChildOfInner extends Outer.Inner { ChildOfInner() { (new Outer()).super(); } }
14 Jak wykonywana jest konstrukcja wyrazenie.super() ?Rozważamy konstrukcję class O { class S {} } class C extends O.S { C() { wyrazenie.super(argumenty); ciag_pozostalych_instrukcji_konstruktora } wyrazenie jest wyliczane. Jeśli jego wartością jest null, wywołanie konstruktora nadklasy kończy się wyjątkiem NullPointerException Niech O będzie klasą bezpośrednią otaczającą statycznie (leksykalnie) klasę (C), w której konstruktorze wystąpiła konstrukcja wyrazenie.super Jeśli wartością wyrazenia nie jest obiekt klasy O ani podklasy klasy O, generowany jest błąd kompilatora Wyrażenia argumenty są wyliczane, od lewej do prawej Konstruktor jest wywoływany
15 Garbage Collector i finalize()Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
16 GC i finalization Środowisko uruchomieniowe Javy utrzymuje tablicę referencji do obiektów. Referencja jest usuwana, gdy obiekt przestaje być widoczny Jawne przypisanie null do zmiennej Gdy nie ma więcej referencji do obiektu, Finalization: użycie System.runFinalization() wywoła finalize() dla wszystkich obiektów czekających na postprzątanie Garbage collection: użycie System.gc() jawnie uruchamia GC
17 Osiągalność referencjiWyznaczanie zbioru referencji nieosiągalnych (unreachable) dla żadnego z wątków programu Jeśli wszystkie referencje do obiektu pochodzą z obiektów nieosiągalnych, sam obiekt jest nieosiągalny Uwaga: dodatkowe warunki jeśli używamy JNI
18 finalization finalize() zaimplementowana w Object (jako pusta metoda), programista może ją przesłonić public class ProcessFile { protected void finalize() throws Throwable { try { file.close(); } finally { super.finalize(); }} (ciekawostka) w J2ME: brak metod związanych z garbage collection; jawne przypisanie null może zasugerować GC możliwość posprzątania obiektu „Reference Objects and Garbage Collection”, artykuł na stronie
19 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
20 interface Action
21 Typy sparametryzowane i JVMProgramy używające generics są tłumaczone do bytecode’u Javy, wykonywanego przez JVM Proces nazywany erasure polega na mapowaniu typów generycznych do typów niesparametryzowanych Niech |T| oznacza erasure typu T, zachodzą wtedy m.in. |T
22 Typy sparametryzowane i tabliceBez generics tablice mają następującą własność: Tablica referencji nadtypu jest nadtypem tablicy referencji podtypu Wynika stąd np. to, że Object[] jest nadtypem String[] Możemy dzięki temu m.in. napisać Object[] objArr = new String[10]; Brak analogicznej własności w przypadku typów sparametryzowanych LinkedList daje błąd kompilacji
23 Dynamiczna informacja o typie i array store checkTablice w Javie zawsze posiadają dynamiczną informację o typie przechowywanych w nich obiektów W czasie wykonywania operacji na tablicach wykonywany jest tzw. array store check, który może spowodować zgłoszenie ArrayStoreException Object objArr = new String[10]; objArr[0] = new Object(); kompiluje się, ale w czasie wykonania zgłaszą wyjątek Programista może zakładać, że tablica zawiera elementy tego samego typu (albo podtypów tego typu) Store check nie jest w ogóle wykonywany w przypadku kolekcji typów sparametryzowanych, bo poniższy kod LinkedList w ogóle się nie skompiluje
24 Typy sparametryzowane i tabliceTablice typów sparametryzowanych nie są dopuszczalne ze względów bezpieczeństwa class Box
25 Typy sparametryzowane i rzutowanieKompilator „nie zna” typu sparametryzowanego przed uruchomieniem programu zadanie utrzymania poprawności rzutowań do typu parametrycznego należy do programisty static Integer foo() { Double d = new Double(1.0); return (Integer) d; } Powyższy kod nie kompiluje się z błędem inconvertible types (znaleziono Double, oczekiwano Integer)
26 Typy sparametryzowane i rzutowaniepublic class BadCast { static
27 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
28 Covariant return typesDo wersji 1.4 języka przesłaniająca implementowaną w nadklasie metoda podklasy musiała mieć identyczną sygnaturę – w szczególności, zwracany typ Poniższy kod nie kompiluje się w JRE 1.4.1_02 class Fruit implements Cloneable { Fruit copy() throws CloneNotSupportedException { return (Fruit) clone(); }} class Apple extends Fruit implements Cloneable { Apple copy() throws CloneNotSupportedException { return (Apple) clone(); Wywołując clone() na obiekcie Apple dostajemy obiekt nadklasy Fruit i musimy niepotrzebnie rzutować w dół do Apple Java 1.5 dopuszcza taką konstrukcję
29 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
30 System typów i autoboxingTypy proste (primitives) i referencyjne (obiekty) Czasem konstrukcja wymaga użycia typu referencyjnego: Jako typu parametryzującego szablon Jako obiektów kolekcji np. List Konieczne rzutowania list.add(new Integer(1)); int i = ((Integer)list.get(0)).intValue(); Autoboxing / autounboxing robi to automatycznie Integer integer = new Integer(1); integer += 1;
31 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
32 Iterowanie po elementach kolekcjiDotychczas (Java 1.4) używamy konstrukcji typu public void drawAll (Collection c) { Iterator itr = c.iterator(); while (itr.hasNext()) { ((Shape)itr.next()).draw(); } Używając typów parametrycznych, możemy zaoszczędzić sobie kodowania kilku rzutowań public void drawAll (Collection
33 Pętla „foreach” + genericsNowa dopuszczalna postać pętli „for” public void drawAll(Collection
34 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
35 Bezpieczne (type-safe) typy wyliczenioweDotychczas class Movement { public static final int UP = 0; public static final int LEFT = 1; public static final int DOWN = 2; public static final int RIGHT = 3; } Wywołanie metody oczekującej parametru takiego typu wyliczeniowego z parametrem np. 5 nie wygeneruje błędu kompilacji Nowa konstrukcja „enum” class Movement { public enum Direction {up, left, down, right}
36 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
37 Statyczne „import” Po użyciu import static java.lang.Math.*;możemy pisać po prostu int i = abs(-1); zamiast kwalifikować dodatkowo nazwą pakietu int i = Math.abs(-1); Potencjalne błędy kompilacji w przypadku powstającej w ten sposób dwuznaczności nazw
38 Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Wyjątki Reflection Tworzenie i zarządzanie obiektami Garbage Collector i finalize() Nowe elementy Javy 1.5 Typy sparametryzowane Covariant return types „autoboxing” Pętla w stylu foreach Bezpieczne (type-safe) enumeracje Statyczne import Metody ze zmienną liczbą parametrów
39 Zmienna liczba argumentówpublic static int sum(int args...) { int sum = 0; for (int x : args ) /* użycie wcześniej przedstawianej konstrukcji „foreach” */ {sum += x; } return sum; }
40 Literatura i URLs Wprowadzenie do użycia Generics Artykuł o tablicach typów sparametryzowanych The Java Language Specification, dostępna z java.sun.com