Wybrane elementy języka Java – ciąg dalszy

Slides:



Advertisements
Podobne prezentacje
Programowanie w Java.
Advertisements

Wstęp do strumieni danych
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Mgr inż.Marcin Borkowski Podstawy Java Krótkie wprowadzenie dla studentów Wyższej Szkoły Ekologii i Zarządzania
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Standardowa biblioteka języka C++
Klasy i obiekty.
Wzorce.
Generics w .NET 2.0 Łukasz Rzeszot.
PROGRAMOWANIE STRUKTURALNE
Tworzenie i obsługa programów – przykład 3 uwagi cd. Wykorzystując różne klasy biblioteki języka Java należy pamiętać w jakim pakiecie się znajdują. Wszystkie.
formatowanie kodu źródłowego
Implementacja ekstensji klasy
Nguyen Hung Son Uniwersytet Warszawski
Programowanie obiektowe w Javie
Wybrane elementy języka Java
Nowa wersja C# Autor: Piotr Sobczak
Serwery Aplikacji ASP .NET Web Objects Arkadiusz Popa.
Model – View - Controler
Bartosz Walter Inżynieria oprogramowania Lecture XXX JavaTM – część II Bartosz Walter
Java – programowanie obiektowe
Język Java Wielowątkowość.
Techniki i języki programowania
Pakiety w Javie Łukasz Smyczyński (132834). Czym są pakiety? Klasy w Javie są grupowane w pewne zbiory zwane pakietami. Pakiety są więc pewnym podzbiorem.
Java 3 MPDI Programowanie obiektowe W7. import java.io.*; public class X { // kontrukcja throws – określenie jakie wyjątki może dana metoda // sygnalizować
PIO 3_2, Zofia Kruczkiewicz1 Wykład 3 – część druga Iteracyjno-rozwojowy cykl oprogramowania 3.
W większości języków programowania biblioteki wejścia/wyjścia ukrywają szczegóły obsługi poszczególnych mediów pod abstrakcją strumienia (ang. stream).
Tworzenie aplikacji mobilnych
Programowanie obiektowe III rok EiT
Programowanie obiektowe – zastosowanie języka Java SE
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
Seminarium problemowe
JAVA.
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
C# Cz.7 Refleksja, Atrybuty
Programowanie obiektowe 2013/2014
Kurs języka C++ – wykład 3 ( )
OCPJP Inner classes.
Kurs języka C++ – wykład 9 ( )
BJUG_1: Typy Generyczne, Kolekcje
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
Kurs języka C++ – wykład 4 ( )
Paweł Starzyk Obiektowe metody projektowania systemów
Programowanie Zaawansowane
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
Typy i metody sparametryzowane (generics) (c) Krzysztof Barteczko 2014.
Implementacja asocjacji (z atrybutami i bez) przy użyciu: referencji (kolekcji referencji) tablic asocjacyjnych przygotował: Kamil Kowalczyk.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
Podstawowe konstrukcje języka Java Bartosz Walter InMoST Wielkopolska sieć współpracy w zakresie innowacyjnych metod wytwarzania oprogramowania Termin.
Programowanie Obiektowe – Wykład 6
Strumienie, Wczytywanie, Zapisywanie, Operacje na plikach
Typy wyliczeniowe, kolekcje
(według:
Delegaty Delegat to obiekt „wiedzący”, jak wywołać metodę.
Programowanie Obiektowe – Wykład 2
Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych
Programowanie obiektowe – zastosowanie języka Java SE
PGO Interfejsy Michail Mokkas.
Założenia projektowe Javy
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
PGO Dziedziczenie Michail Mokkas.
Programowanie w Javie 1 Dr Robert Kowalczyk
PGO Porównywanie obiektów
Zapis prezentacji:

Wybrane elementy języka Java – ciąg dalszy Paweł Zdziarski

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

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

Typy sparametryzowane Obecne w np. C++ Używane najczęściej w kontekście różnych operacji na kolekcjach W Javie 1.4 (i wcześniejszych) musimy używać rzutowania List myIntList = new LinkedList(); myIntList.add(new Integer(0)); Integer x = (Integer) myIntList.iterator().next(); aby zapewnić poprawność typów w czasie wykonania. Kompilator wie jedynie, że obiekt typu LinkedList przechowuje elementy typu Object Użycie generics w Javie 1.5 List<Integer> myIntList = new LinkedList<Integer>(); Integer x = myIntList.iterator().next();

Typy sparametryzowane - składnia Deklaracja: używamy formalnego parametru typu, np. public interface List<E> { void add(E x); Iterator<E> iterator(); } Wywołanie: typ sparametryzowany, np. List <Integer> myList; „intuicyjne” rozumienie wywołania: każde wystąpienie formalnego parametru typu w deklaracji typu sparametryzowanego zastępujemy faktycznym parametrem typu, np. zastępujemy we wszystkich metodach List<E> wystąpnienia E typem Integer W rzeczywistości, skompilowany kod typu sparametryzowanego istnieje tylko w jednej kopii (jeden plik klasy .class)

Typy sparametryzowane - wildcards Jak napisać metodę wypisującą wszystkie elementy kolekcji? void printCollection(Collection<Object> c) { for (Object e : c) { System.out.println(e);}} (używamy dodatkowo nowej postaci pętli for) Skoro Collection<Object> nie jest nadtypem innej sparametryzowanej kolekcji, musielibyśmy stworzyć odpowiednie metody do wypisywania elementów Collection<String> etc. Collection<?> jest nadtypem wszystkich kolekcji. ? Jest typem wildcard void printCollection(Collection<?> c) { for (Object e : c) { System.out.println(e);}}

Typy sparametryzowane – bounded wildcards Nawet jeśli Shape jest nadtypem Circle, Rectangle etc., List<Shape> nie jest nadtypem List<Circle>, List<Rectangle> Możemy jawnie zadeklarować tzw. upper bound parametru typu List <? extends Shape>

Typy sparametryzowane – implementacja, erasure Problem używania kodu generics z kodem wcześniejszych wersji Javy public String loophole(Integer x) { List<String> ys = new LinkedList<String>; List xs = ys; xs.add(x); ys.iterator().next(); } Jak we wcześniejszym przykładzie, tworzymy alias xs do zmiennej ys typu spararametryzowanego List<String> Tutaj kod się kompiluje (kompilator daje jedynie ostrzeżenie), natomiast użycie błędnego typu daje błąd wykonania (ClassCastException) return (String) ys.iterator().next(); Implementacja generics działa jako przód (front-end) normalnego kompilatora Javy, kod z użyciem generics jest zamieniany na normalny bytecode Javy w trakcie procesu nazwanego erasure

Typy sparametryzowane – implementacja, erasure Kod sparametryzowany public String loophole(Integer x) { List<String> ys = new LinkedList<String>; List xs = ys; xs.add(x); ys.iterator().next(); } zostanie przetłumaczony do public String loophole(Integer x) { List ys = new LinkedList; return (String) ys.iterator().next(); // run time error Podwójna kontrola typów: translator sprawdza poprawność użycia typów sparametryzowanych (np. nie moglibyśmy zadeklarować List<Object> xs) Do wynikowego kodu „zwykłej” Javy dodawane są rzutowania wszędzie, gdzie może wystąpić niepoprawne (pod wzgl. typów) przypisanie

Typy sparametryzowane - erasure Mechanizm polega na mapowaniu typów sparametryzowanych do typów niesparametryzowanych Erasure klasy niesparametryzowanej nie zmienia definicji tej klasy Typy sparametryzowane tracą typ parametru Tree<T>  Tree Tree<Integer>  Tree Typ parametru jest mapowany do swojego upper bound T (w klasie Tree)  Object ale Bush <T extends Color> T (w klasie Bush)  Color Wstawiane są odpowiednie rzutowania

Typy sparametryzowane - erasure Czy skopiluje się class ShoppingCart<T extends DVD>{ // ... } class ShoppingCart<T extends VideoTape>{ ? Nie: po erasure, obie klasy miałyby tą samą nazwę

Typy sparametryzowane - erasure Czy skompiluje się class TwoForOneSpecial<T extends Rentable, W extends Rentable> { public void add(T newRentable) { //... } public void add(W newRentable) { }? Nie: po erasure, obie metody mają te same sygnatury

Typy sparametryzowane - erasure Czy skompiluje się class GetAFreeVideoTape<T extends Rentable, W extends VideoTape> { public void add(T anything) { //... } public void add(W videotape) { ? Tak: po erasure dostaniemy kod odpowiadający class GetAFreeVideoTape { public void add(Rentable anything) { public void add(Videotape videotape) {

Typy sparametryzowane – jeden kod klasy Dlaczego nie jest poprawna konstrukcja class MyClass<T> { static T member; } ? Tworząc wiele instancji typu sparametryzowanego, np. MyClass<Integer> myIntClass; MyClass<String> myStringClass; mielibyśmy tylko jedną kopię member w pamięci. Jakiego typu byłaby ta zmienna?

Typy sparametryzowane – jeden kod klasy Jaki wynik da wykonanie List <String> l1 = new ArrayList<String>(); List<Integer> l2 = new ArrayList<Integer>(); System.out.println(l1.getClass() == l2.getClass()); ? Ponieważ kod z użyciem generics i tak jest tłumaczony do kodu bez typów sparametryzowanych, wszystkie instancje klas sparametryzowanych są tej samej klasy true

Typy sparametryzowane i dziedziczenie Fragment kodu List<String> ls = new ArrayList<String>(); List<Object> lo = ls; daje błąd kompilacji w linii 2 Intuicyjne rozumienie List<Object> jako nadtypu List<String> nie jest poprawne! Rozważając lo.add(new Object()); String s = ls.get(0); Wcześniej stworzyliśmy alias do obiektu lo o nazwie ls W pierwszej linii wstawiamy do listy element typu Object – nie ma już gwarancji, że lista przechowuje elementy wyłącznie typu String Jeśli cały kod kompilowałby się, druga linia nie zachowywałaby poprawności typów Ogólnie, mimo iż A extends B to jednak List<B> nie jest podtypem List<A>

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

Covariant return types Do 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ę

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

Iterowanie po elementach kolekcji Dotychczas (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<Shape> c) { Iterator<Shape> itr = c.iterator(); while (itr.hasNext()) { itr.next().draw(); }

Pętla „foreach” + generics Nowa dopuszczalna postać pętli „for” public void drawAll(Collection<Shape> c) { for (Shape s:c) s.draw(); } Rozwijane automatycznie do kodu for (Iterator<Shape> $i = c.iterator(); $i.hasNext();) { Shape s = $i.next();

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

Bezpieczne (type-safe) typy wyliczeniowe Typ wyliczeniowy – obecny w C, C++, C#, Pascalu Dotychczas public class Karty { public static final int PIK = 0; public static final int TREFL = 1; public static final int KARO = 2; public static final int KIER = 3; } Użycie wzorca (pattern) zamiast konstrukcji języka Potencjalne problemy Metoda oczekująca Karty skompiluje się nawet, jeśli jako parametr przekażemy literał np. 5 Optymalizacja przez kompilator – inlining

Typy wyliczeniowe - inlining Kompilator optymalizuje kod binarny włączając wartości stałych bezpośrednio do każdej klasy, która ich używa Zgodnie ze specyfikacją języka, narzędzia mogą, ale nie muszą wspierać model rozproszonej pracy nad aplikacją i automatycznie rekompilować klasy używane przez program public class Test { public Test() } static public void main(String[] args) System.out.println(Karty.KARO); Po zrekompilowaniu klasy Karty i zmianie wartości stałej KARO uruchomienie klasy Test (poza IDE) da rezutat identyczny jak przed zmianą stałej

Typy wyliczeniowe – wzorzec typesafe enum Zdefiniuj klasę reprezentującą pojedynczy element „typu wyliczeniowego” (UWAGA: system typów Javy 1.4 nie obejmuje typu wyliczeniowego) Nie udostępniaj żadnych publicznych konstruktorów Jedynie pola public static final Nigdy nie stworzymy obiektów tego typu poza tymi udostępnianymi przez pola public static final public class KartyPattern { public final String nazwa; private KartyPattern(String nazwa) {this.nazwa = nazwa;} public String toString() {return nazwa;} public static final KartyPattern PIK = new KartyPattern("pik"); public static final KartyPattern TREFL = new KartyPattern("trefl"); public static final KartyPattern KARO = new KartyPattern("karo"); public static final KartyPattern KIER = new KartyPattern("kier"); }

Typy wyliczeniowe – wzorzec typesafe enum Użycie wzorca typesafe enum gwarantuje poprawność wykonania (runtime) Jeśli zdefiniujemy metodę oczekującą parametru typu KartyPattern mamy pewność, że każda niezerowa (non-null) referencja przekazana do tej metody reprezentuje poprawny kolor karty Stałe mogą być dodane do takiej klasy bez rekompilowania klas-klientów Stałe nigdy nie są wkompilowane do klas ich używających (klientów) Możemy zmienić metodę toString() aby uzyskać sensowną reprezentację stałych na ekranie Porównywanie stałych odbywa się przez dziedziczoną z Object metodę equals wykonującą porównanie referencji, a nie np. kosztowne porównywanie String’ów Wady: Klasy J2SE i API’s produktów opartych na Javie rzadko używają wzorca typesafe enum, jest on generalnie mało popularny Kod znacznie się rozrasta, jeśli chcemy dodać serializację klasy, uporządkowanie wartości etc.

Wzorzec typesafe enum – problemy z serializacją Dodajemy public class KartyPattern implements Serializable Poniższy kod ByteArrayOutputStream bout = new ByteArrayOutputStream (); ObjectOutputStream out = new ObjectOutputStream (bout); KartyPattern kp = KartyPattern.KARO; out.writeObject (kp); out.flush (); ByteArrayInputStream bin = new ByteArrayInputStream (bout.toByteArray ()); ObjectInputStream in = new ObjectInputStream (bin); KartyPattern kp2 = (KartyPattern) in.readObject (); System.out.println ((kp2 == KartyPattern.KARO || kp2 == KartyPattern.KIER || kp2 == KartyPattern.PIK || kp2 == KartyPattern.TREFL)); Wypisuje False W klasie implementującej Serializable musielibyśmy przesłonić metodę readResolve(), żeby upewnić się, że podczas deserializacji nie zostanie stworzona nowa instancja klasy, a użyte będzie stworzone wcześniej statyczne pole..

Typy wyliczeniowy w Java 1.5 Wbudowany w specyfikację języka nowy typ: wyliczeniowy (enum) enum Karta (pik, trefl, karo, kier); W odróżnieniu od klas wzorca typesafe enum, zmienne takiego typu mogą być używane w klauzuli switch Karta karta; switch karta{ case Karta.pik ... } Nie są konieczne zmiany JVM Implementowane przez kompilator Nowa klasa java.lang.Enum, po której dziedziczą wszystkie zmienne typu wyliczeniowego Deklaracja jest nowym rodzajem deklaracji klasy W szczególności, nie jest legalne jawne tworzenie instancji enumeracji przy użyciu new()

Typy wyliczeniowy w Java 1.5 A Typesafe Enum Facility for the Javatm Programming Language http://www.jcp.org/aboutJava/communityprocess/jsr/tiger/enum.html Effective Java Programming: Substitutes for Missing C Constructs http://java.sun.com/developer/Books/shiftintojava/page1.html#replaceenums Typesafe Enum: Using enum in J2SE 1.5 (Tiger) http://www.langrsoft.com/articles/enum.html Beware of Java typesafe enumerations http://www.javaworld.com/javaworld/javatips/jw-javatip122.html

Literatura i URLs Wprowadzenie do użycia Generics http://developer.java.sun.com/developer/technicalArticles/releases/generics/ The Java Language Specification, dostępna z java.sun.com