c documents and settings peofesional application data opera opera profile cache4 opr00vue

Upload: milos-markovic

Post on 08-Jul-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    1/33

     

    Generiko programiranje

      Zašto Generiko Programiranje?

      Definisanje Jednostavne Generike Klase  Generike Metode

      Granice za Tipovske Promenljive

      Generiki Kod i Virtualna Mašina

      Zabrane i Ogranienja

      Pravila Nasleivanja za Generike Tipove

      “Džoker” Tipovi

      Refleksija i Generici 

    Od verzije 1.0 generici  su doživeli  najznaajnije promene u programskom jeziku Java.Dodavanje generika JDK-u 5.0 je posledica jedne od prvih Java Specifikacionih Zahteva(Java Specification Requests eng.), JSR 14, koji je nastao 1999. godine. Grupa strunjaka je provela pet godina radei na specifikacijama i probnim implementacijama. Generici  su poželjni  jer dozvoljava ju pisanje koda koji je sigurniji i lakši za itanje odkoda zasut  Object   promenljivama i kastovanjem. Generici  su  narocito korisni  zakolekcijske klase, kao što je svuda prisutna klasa ArrayList.Generici  su  - bar na prvi pogled - slini  šablonima  u C++-u.  U C++-u, kao i u Javi,šabloni su prvo dodati jeziku kao podrška strogo tipiziranim kolekcijama. Meutim,

    tokom godina, otkrivene su i druge upotrebe. Možda ete nakon itanja ovog poglavlja,pronai novu svrhu za Java generike u vašim programima.

     Zašto Generi  ko Programiranje?

    Generiko programiranje predstavlja pisanje koda koji može biti isponova korišen zaobjekte razliitih tipova. Na primer, ne želite da programirate odvojene klase za kolekcijuString i File objekata. I ne morate – jedna jedina klasa ArrayList  pravi kolekciju objekatabilo koje klase. Ovo je jedan od primera generikog programiranja.Pre JDK 5.0, generiko programiranje je postizano pomou nasle ivanja. Klasa ArrayList  

     jednostavno sadrži niz Object  referinci:public class ArrayList // pre JDK 5.0{public Object get(int i) {. . .}public void add(Object o) {. . .}. . .private Object[] elementData;

    }

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    2/33

     Postoje dva problema u ovom pristupu. Kad god vraamo vrednost kastovanje jeneophodno:

    ArrayList files = new ArrayList();. . .String filename = (String) names.get(0);

    Šta više, ne postoji provera greške. Možete dodati vrednost bilo koje klase:

    files.add(new File(“. . .”));

    Ovaj poziv se prevodi i izvršava bez greške. Meutim, kastovanje rezultata od get uString e prijaviti grešku.JDK 5.0 nudi bolje rešenje:  parametre tipa. Klasa  ArrayList   sada sadrži tip parametrakoji ukazuje na tip elementa:

    ArrayList files = new ArrayList();

    Ovo ini vaš kod itljivijim. Može se odmah videti da baš ova nizovska lista sadržiobjekte tipa String.Kompilator, takoe može nai dobru primenu ovih informacija. Prilikom poziva get nijepotrebno kastovanje: kompilator zna da je povratni tip String, ne Object:

    String filename = files.get(0);

    Kompilator takoe zna da metod add  iz ArrayList ima parametar tipa String. To je sigurnije nego da imamo Object parametar. Sada kompilator može da proveri da li steubacili objekat pogrešnog tipa. Na primer, iskaz:files.add(new File(“...”));//može dodati String objekte u

    //ArrayList

    se nee kompilirati. Greška prilikom kompiliranja je mnogo bolja nego liizbacivanje izuzetka klasnog kastovanja prilikom izvršavanja. Ovo je privlanostparametara tipa : oni ine vaš program lakšim za itanje i sigurnijim.

     Ko Želi Biti Generi  ki Programer? 

    Lako je koristiti generike klase kao što je  ArrayList.  Veina Java programera e jednostavno koristiti tipove kao što je ArrayList, kao da su ugraeni u jezik, istokao String[ ].( Naravno, nizovske liste su bolje od nizova jer se mogu proširivatiautomatski.)Meutim nije tako lako implementirati generiku klasu. Programeri koji koriste vaš kode želeti da ubace sve vrste klasa za vaše parametre tipa. Oni oekuju da sve radi bezveih ogranienja i zbunjujuih poruka o grešci. Zato je vaš posao generikog programerada predvidite sve potencijalne mogunosti korišenja vaše klase.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    3/33

    Koliko teško ovo može biti? Evo tipinog ishoda sa kojim stvaraoci bibliotekestandardnih klasa treba da se izbore. Klasa ArrayList  ima metod addAll za dodavanje svihelemenata neke druge kolekcije. Programer e možda želeti da doda sve elemente iz ArrayList  u  ArrayList.  Ali, naravno, obrnuto ne bi smelo dabude dozvoljeno. Kako da dozvolite jedan poziv, a zabranite drugi? Stvaraoci Java jezika

    su izmislili genijalni nov koncept, “džoker” tip ( wildcard type eng.) , da reše ovajproblem. “Džoker” tipovi su poprilino apstraktni, ali oni omoguuju stvarocu bibliotekeda napravi što je mogue fleksibilnije metode.Generiko programiranje upada u jedan od tri nivoa veštine. Na osnovnom nivou, samokoristite generike klase – tipine kolekcije kao što je ArrayList –  baz razmišljanja kako izašto one rade. Veina aplikacijskih programera e želeti da ostane na tom nivou doknešto ne poe naopako. Možete se susresti sa zbunjujuim porukama o grešci prilikommešanja razliitih generikih klasa, ili prilikom povezivanja sa zastarelim kodom koji nezna ništa o parametrima tipa. U tom trenutku, trebalo bi da nauite dovoljno o Javagenericima da biste sistematino rešili problem bolje nego nasuminim krpljenjem. Nakraju ete, naravno, možda poželeti da implementirate vašu sopstvenu generiku klasu ili

    metod.Aplikacijski programeri verovatno nee pisati dosta generikog koda. Ljudi iz Sun-a suve  odradili teži deo i snabdeli parametrima tipa sve kolekcijske klase. Po nekomupotrebnom pravilu, jedino kod koji je tradicionalno ukljuivao mnogo kastovanja opštihtipova ( kao što je Object ili Comparable  interfejs) e imati koristi od korišenjaparametara tipa.U ovom poglavlju emo vam rei sve što treba da znate da biste implementirali vašgeneriki kod. Meutim, od veine italaca oekujemo da koriste ovo znanje, u osnovi,kao pomo  prilikom rešavanja problema, i da zadovolje znatiželju o unutrašnjemfunkcionisanju parametrizovanih kolekcijskih klasa.

     Definisanje Jednostavne Generi  ke KlaseGenerika klasa je klasa sa jednom ili više tipskih promenljivih. U ovom poglavljukoristimo, kao primer, jednostavnu klasu Pair.  Ova klasa nam dozvoljava da sefokusiramo na generike bez ometanja od strane detalja oko skladištenja podataka. Evokod generike klase Pair: 

    public class Pair 

     {public Pair() {first = null; second = null;}public Pair(T first, T second)

    {this.first = first;this.second = second;}

    public T getFirst (){ return first;}public T getSecond (){ return second;}

    public void setFirst(T newValue) { first = newValue;}public void setSecond(T newValue) { second = newValue;}

    private T first;private T second;

    }

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    4/33

     Klasa Pair  uvodi tipsku promenljivu T, izmeu uglastih zagrada < >, nakon imena klase.Generika klasa može imati više od jedne tipske promenljive. Na primer, možemodefinisati klasu Pair  sa odvojenim tipovima za prvo i drugo polje:

    public class Pair {. . .}

    tipske promenljive su korišene kroz klasu da specifikuju tipove koje vraa metod itipove polja i lokalnih promenljivih. Na primer,private T first;//koristi tipsku promenljivu

    NAPOMENA: Uobiajena je praksa da se tipske promenljive pišu velikim slovima, i da budu kratke. Javabiblioteka koristi promenljivu E za tip elementa u kolekciji, K i V za tipove kljua i vrednosti tabele, i T ( iokolna slova U i S , ako je neophodno) za bilo koji drugi tip.

    Generiki tip se instancira tako što se zamene tipske promenljive sa tipom promenljive ,kao što je

    Pair 

    Možete kao rezultat smatrati obinu klasu sa konstruktorima Pair ()Pair ( String, String )

    i metodamaString getFirst() String getSecond()void setFirst(String)void setSecond(String)

    Drugim reima, generika klasa se ponaša kao fabrika obinih klasa.Program u Primeru 13-1 stavlja klasu Pair  u upotrebu. Statiki metod minmax prolazi nizi simultano izraunava minimalnu i maksimalnu vrednost. Koristi objekat Pair   da bi

    vratio oba rezultata. Setimo se da compareTo metoda poredi dva stringa, vraa 0 ako sustringovi jednaki, negativni ceo broj ako se prvi string nalazi ispred drugog uleksikografskom poretku, i pozitivni ceo broj inae.

    C++ NAPOMENA:  Površno gledano, generike klase u Javi su sline šablonskim klasama u C++-u.Jedina oigledna razlika je u tome što u Javi ne postoji specijlna rezervisana re template. Meutim, kao štoete videti kroz ovo poglavlje, potoji bitna razlika izmeu ova dva mehanizma.

    Primer 13- 1 PairTest1.java

    1. public class PairTest1

    2. {3. public static void main(String[] args)4. {5. String[] words = { "Mary", "had", "a", "little", "lamb" };6. Pair mm = ArrayAlg.minmax(words);7. System.out.println("min = " + mm.getFirst());8. System.out.println("max = " + mm.getSecond());9. }10. }11.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    5/33

    12. class ArrayAlg13. {14. /**15. Uzima minimum i maksimum iz niza stringova16. @parametar a je niz stringova17. @vraa par sa minimalnom i maksimalnom vrednošu18. ili null ako je nula ili prazan

    19. */20. public static Pair minmax(String[] a)21. {22. if (a == null || a.length == 0) return null;23. String min = a[0];24. String max = a[0];25. for (int i = 1; i < a.length; i++)26. {27. if (min.compareTo(a[i]) > 0) min = a[i];28. if (max.compareTo(a[i]) < 0) max = a[i];29. }30. return new Pair(min, max);31. }

    32. } 

    Generi  ke Metode

    U predhodnom odeljku, videli ste kako se definiše generika klasa. Možete takoedefinisati jedan jedini metod sa parametrom tipa.

    class ArrayAlg{

    public static T getMiddle(T[] a){

    return a[a.length / 2]);}

    }

    Ovaj metod je definisan unutar obine klase, ne unutar generike klase. Meutim , to jegeneriki metod, kao što se vidi iz uglastih zagrada i tipovske promenljive. Napomenimoda je tipovska promenljiva ubaena nakon modifikatora ( public static, u  našemsluaju)i pre povratnog tipa.Možete definisati generiki metod i unutar obine klase i unutar generike klase.Prilikom poziva generikog metoda, možete staviti stvarni tip, izmeu uglastih zagrada,pre naziva metode:

    String[] names = { "John", "Q.", "Public" };String middle = ArrayAlg.getMiddle(names);

    U ovom sluaju (i u stvari u veini sluajeva), možete izostaviti tip prametra iz poziva metode. Kompilator ima dovoljno informacija da zakljui koji stemetod želeli. Usaglašava tip od names  ( koji je  String[]  ) sa generikim tipom T[] izkljuuje da T mora biti String. To jest, možete jednostvno pozvati

    String middle = ArrayAlg.getMiddle(names);

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    6/33

    C++ NAPOMENA: U C++-u, stavljate tip parmetara iza naziva metode. To može dovesti do neprijatnihdvosmislenosti u rašlanjivanju. Na primer, g( f< a, b >(c) ) može znaiti "pozovi g sa rezultatom od f< a,b >(c) ", ili "pozovi g sa dve Boolean vrednosti f< a i b >(c)" 

    Granice za Tipovske Promenljive 

    Ponekad, klasa ili metod treba da stave ogranienja na tipove promenljivih. Evo tipinogprimera. Želimo da izraunamo najmanji element niza:

    class ArrayAlg{

    public static T min(T[] a) // skoro ispravno{

    if (a == null || a.length == 0) return null;T smallest = a[0];for (int i = 1; i < a.length; i++)

    if (smallest.compareTo(a[i]) > 0) smallest = a[i];return smallest;

    }}

    Ali postoji problem. Pogledajte kod metode min. Promenljiva smallest  je tipa T, što znaida može biti objekat proizvoljne klase. Kako mi da znamo da klasa kojoj pripada T imacompareTo metod?Rešenje je da ograniimo T na klase koje implementiraju Comparable interfejs –standardni interfejs sa jednom metodom, compareTo. To se postiže postavljanjem granica(bound eng.) za tip promenljive T:public static T min(T[] a) . . .

    U stvari, Comparable interfejs je sam po sebi generiki tip. Za sada emo ignorisati tusloženost.Sada generiki metod min može biti pozvan samo sa nizovima klasa koje implementirajuComparable interfejs, kao što je String, Date i tako dalje. Poziv min sa nizom Rectangle e proizvesti grešku prilikom kompiliranja jer klasa  Rectangle ne implementira Comparable.

    C++ NAPOMENA: U C++-u, ne možete ograniiti tipove parametara šablona. Ako progremer instancirašablon sa neodgovarajuim tipom, javlja se (naješe nejasna) poruka o grešci unutar koda šablona.

    Možda se pitate zašto koristimo rezervisanu re  extends  pre nego rezervisanu re implements u ovoj situaciji – ipak, Comparable je interfejs. Zapis

    izražava da T treba da bude podtip (subtype eng.) od ograniavajueg tipa. I T iograniavajui tip mogu biti bilo klasa bilo interfejs. Rezervisana re extends je odabrana

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    7/33

     jer je prihvatljiva slinost sa konceptom podtipa, i Java dizajneri nisu želeli da dodajunovu rezervisanu re( kao što je sub) u jezik.Promenljive tipa ili "džoker" mogu imati višestruka ogranienja, na primer 

    T extends Comparable & Serializable

    Ograniavajui tipovi su razdvojeni ampersendom (&) jer su zarezi iskorišeni darazdvoje promenljive tipa.Kao i sa Java nasleivanjem, možete imati koliko želite interfejs supertipova, ali najviše jedno od ogranienja može biti klasa. Ako imate klasu kao ogranienje, ona se moranavesti prva u listi ogranienja. U sledeem uzorku programa (Primer 13-2), ponovo smo napisali minmax metod tako dabude generiki. Metod izraunava minimum i maksimum generikog niza, vraaPair.

    Primer 13-2: PairTest2.java 

    1. import java.util.*;2.3. public class PairTest24. {5. public static void main(String[] args)6. {7. GregorianCalendar[] birthdays =8. {9. new GregorianCalendar(1906,Calendar.DECEMBER, 9),//G. Hopper10. new GregorianCalendar(1815, Calendar.DECEMBER, 10),

    // A. Lovelace11. new GregorianCalendar(1903, Calendar.DECEMBER, 3),

    // J. von Neumann

    12. new GregorianCalendar(1910, Calendar.JUNE, 22),// K. Zuse13. };14. Pair mm = ArrayAlg.minmax(birthdays);15. System.out.println("min = " + mm.getFirst().getTime());16. System.out.println("max = " + mm.getSecond().getTime());17. }18. }19.20. class ArrayAlg21. {22. /**23. uzima minimum i maksimum iz niza objekata tipa T24. @parametar a je niz objekata tipa T

    25. @vraa par sa vrednošu minimuma i maksimuma,ili26. nula ako je nula ili prazan27. */28. public static Pair minmax(T[] a)29. {30. if (a == null || a.length == 0) return null;31. T min = a[0];32. T max = a[0];33. for (int i = 1; i < a.length; i++)34. {

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    8/33

    35. if (min.compareTo(a[i]) > 0) min = a[i];36. if (max.compareTo(a[i]) < 0) max = a[i];37. }38. return new Pair(min, max);

    Generi  ki Kod i Virtualna Mašina

    Virtualna mašina nema objekte generikih tipova – svi objekti pripadaju obinimklasama. Ranije verzije implementacije generika su bile sposobne da kompilirajuprogram koji koristi generike unutar klasnog fajla koji se izvršava na 1.0 virtualnojmašini! Ova nazadna kompatibilnost je napuštena poprilino kasno u razvoju Javagenerika. Ako koristite Sun-ov kompilator da kompilirate kod koji koristi Java generike,rezultujui klasni fajl se nee izvršiti na virtualnim mašinama pre verzije 5.0.

    NAPOMENA:  Ako želite da imate koristi od JDK 5.0 jezikih karakteristika istovremeno zadržavajuibajtkod kompatibilnost sa starim virtualnim mašinama, pogledajtehttp:/sourceforge.net/project/retroweaver. Retroviver (retroweaver eng.) program ponovo piše klasni fajl

    tako da bude kompatibilan sa starijim virtualnim mašinama.

    Kad god definišete generiki tip, odgovarajui izvorni (raw eng.) tip se automatskiobezbeuje. Naziv osnovnog tipa je jednostavno ime generikog tipa, sa odstranjenimtipom parametara. Tip promenljivih je obrisan  i zamenjen njegovim graninimtipovima(ili Object -om za promenljive bez ogranienja.)

    Na primer, izvorni tip za Pair izgleda ovako:

    public class Pair{

    public Pair(Object first, Object second){this.first = first;this.second = second;

    }

    public Object getFirst() { return first; }public Object getSecond() { return second; }

    public void setFirst(Object newValue) { first = newValue; }public void setSecond(Object newValue) { second = newValue; }

    private Object first;private Object second;

    }

    Zato što je T neogranien tip promenljive, jednostavno je zamenjen sa Object. Rezultat je obina klasa, baš kao što ste je možda implementirali pre nego što su genericidodati programskom jeziku Java.Vaši programi mogu sadržati razliite Pair, kao što su Pair  iliPair, ali brisanje ih sve pretvara u osnovne Pair  tipove.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    9/33

    C++ NAPOMENA:  U ovom pogledu, Java generici se dosta razlikuju od C++ šablona. C++ proizvodirazliite tipove za svaku instancu šablona, fenomen nazvan “template code bloat“. Java ne pati od ovogproblema.

    Izvorni tip zamenjuje promnljive tipa sa prvom granicom, ili Object  –om ako nije zadana

    granica. Na primer, promenljiva tipa u klasi Pair  nema izri

    ito navedene granice,zbog ega osnovni tip zamenjuje T sa Object– om. Predpostavimo da smo deklarisalimalko drugaiji tip

    public class Interval implementsSerializable{

    public Interval(T first, T second){

    if (first.compareTo(second) .  U tom luaju izvorni tip zmenjuje T sa Serializable, i kompilator ubacuje kastovanje u Comparable kad je to neophodno. Zbog efikasnosti, trebali bi zato staviti oznaavajue interfejse (tj.interfejse bez metoda) na kraj liste ogranienja.

     Prevo enje Generi  kih Izraza

    Kada programirate poziv generikog metoda, kompilator ubacuje kastovanje ukoliko jepovratni tip obrisan. Na primer, razmotrimo redosled iskaza

    Pair buddies = . . .;

    Employee buddy = buddies.getFirst();

    Brisanje  getFirst   ima povratni tip Object . Kompilator automatski ubacuje kastovanje u Employee. U stvari, kompilator prevodi poziv metoda u dve instrukcije virtualne mašine:

    -  poziv izvornog metoda Pair.getFirst

    -  kastovanje povratnog tipa Object  u tip  Employee

    Kastovanje se takoe ubacuje kada pristupate generikom polju. Predpostavimo da suprvo i drugo polje klase Pair  javni(možda nije dobar programerski stil, ali je ispravan uJavi.)

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    10/33

     Employee buddy = buddies.first;takoe ubacuje kastovanje u krajnji bajt kod.

     Prevo enje Generi  kih Metoda

    Brisanje tipa se takoe javlja i u generikim metodama. Programeri obino zamišljajugenerike metode kao

    public static T min(T[] a)

    kao celu familiju metoda, ali nakon brisanja, ostaje samo jedan metod:public static Comparable min(Comparable[] a)

    Primetimo da je parametar tipa T obrisan, ostavljajui jedino granini tip Comparable.Brisanje kod metoda dovodi do nekoliko komplikacija. Razmotrimo ovaj primer:

    class DateInterval extends Pair{

    public void setSecond(Date second){

    if (second.compareTo(getFirst()) >= 0)super.setSecond(second);

    }. . .

    }

    Interval datuma je par  Date  objekata, i želeemo da nadjaamo metode da bismoosigurali da druga vrednost ne bude manja od prve. Ova klasa je obrisana u

    class DateInterval extends Pair // nakon brisanja

    { public void setSecond(Date second) { . . . }. . .

    }

    Možda iznenaujue, postoji drugi metod setSecond  , nasleen iz Pair -a , to jestpublic void setSecond(Object second)

    ovo je oigledno drugaiji metod jer mu je parametar tipa razliit—Object  umesto Date.Ali ne bi trebalo da su razliiti. Razmotrimo ovaj redosled iskaza:

    DateInterval interval = new DateInterval(. . .);Pair pair = interval; // OK—dodeljivanje superklasipair.setSecond(aDate);

    Mi oekujemo da je poziv setSecond  polimorfan i da je pozvan odgovarajui metod. Zatošto par pripada DateInterval objektu, trebalo bi da bude DateInterval.setSecond . Problem je što je brisanje tipa ometa polimorfizam. Da bi rešio ovaj problem, kompilator generišematod premošivanja (bridge mathod eng.) u klasi DateInterval:

    public void setSecond(Object second){ setSecond((Date) second); }

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    11/33

    Da bismo videli zašto ovo funkcioniše, hajde da pažljivo pratimo izvršenje iskazapair.setSecond(aDate)

    Promenljiva pair  ima deklarisan tip Pair , i taj tip ima samo jedan metod nazvansetSecond , to jest setSecond(Object). Virtualna mašina poziva taj metod na objektu kojem pair pripada. Taj objekat je tipa  DateInterval.  Zbog toga, je pozvan metod  DateInterval.setSecond(Object). Taj metod je sintetizovan metod premošivanja. Onpoziva DateInterval.setSecond(Date), što smo i želeli.Metodi premošivanja mogu biti i neobiniji. Predpostavimo da metod  DateIntervaltakoe nadjaava metod getSecond :class DateInterval extends Pair{

    public Date getSecond(){ return (Date) super.getSecond().clone(); }

    . . .}

    U obrisanom tipu, postoje dva getSecond  metoda:Date getSecond() // definisan u DateIntervalObject getSecond() // definisan u Pair

    Ne možete pisati Java kod na taj nain - bilo bi neispravno da imamo dve metode sa istimtipovima parametara – u ovom sluaju, bez parametra. Meutim, u virtualnoj mašini,tipovi parametara i povratni tip  odreuju metod. Zato, kompilator može da proizvedebajtkod za dva metoda koji se razlikuju smo u povratnom tipu, i virtulna mašina e se uovoj situaciji snai korektno.

    NAPOMENA: Metode premošivanja nisu ograniene generikim tipovima. Ve smo zapazili u odeljku 5da, poevši sa JDK verzijom 5.0, je ispravno da metod specifikuje restriktivniji povratni tip kad prevazilazidrugi metod. Na primer

    public class Employee implements Cloneable{

    public Employee clone() throws CloneNotSupportedException { ... }}

    Kaže se da Object.clone i Employee.clone metode imaju kovarjantne povratne tipove.

    U stvari, klasa Employee ima dve klon metode:

    Employee clone() // definisan iznadObject clone() // sintetizovan metod premošivanj,

    // prevazilazi Object.cloneSintetizovan metod premošivanja poziva novije definisan metod.

    Da sumiramo, treba da zapamtite ove injenice o prevodu Java generika:-

      Nema generika u virtualnoj mašini, samo obinih klasa i metoda.-  Svaki tip parametara je zamenjen svojim ogranienjem.-

      Metode premošivanja su sintetizovane da sauvaju polimorfizam.-

      Kastovanje se ubacuje ako je neophodno da sauva sigurnost tipa.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    12/33

     

     Poziv Nasle enog Koda 

    Dosta Java koda je napisano pre JDK 5.0. Da generike klase ne mogu da rade sa timkodom, verovatno ne bi bile u širokoj upotrebi. Sreom, jednostavno je koristiti generikeklase zajedno sa njihovim izvornim ekvivalentima u nasleenim API  –jima.Pogledajmo konkretan primer. Da podesimo etiketu od Jslider, koristimo metod

    void setLabelTable(Dictionary table)

    U Poglavlju 9, koritili smo sledei kod da uvedemo matricu etiketa:Dictionary labelTable = new Hashtable();labelTable.put(0, new JLabel(new ImageIcon("nine.gif")));labelTable.put(20, new JLabel(new ImageIcon("ten.gif")));. . .slider.setLabelTable(labelTable); // UPOZORENJE

    NAPOMENA: Klasa Hashtable je konkretna potklasa apstraktne klase Dictionary. I Dictionary i Hahtable su bile deklarisane kao “zastarele“ pošto su zamenjene Map interfejsom i klasom HashMap od verzije JDK1.2. iako su oigledno žive i funkcionišu. Ipak, klasa Jslider  je dodana samo JDK-u 1.3. Nisu li programeritada znali za klasu Map? Da li vas ovo ini punim nade da e uvojiti generike u bliskoj budunosti? Dobro,tako to ide sa nasleenim kodom.

    U JDK-u 5.0, klase  Dictionary i Hahtable su pretvorene u generiku klasu. Prema tome,sposobni smo da napravimo  Dictionary  umesto da koristimoizvorni Dictionary. Meutim, kada prosledite  Dictionary objekatsetLabelTable, kompilator objavljuje upozorenje.

    Dictionary labelTable = . . .;

    slider.setLabelTable(labelTable); // UPOZORENJEIpak, kompilator ne garantuje šta setLabelTable može da uradi sa  Dictionary objektom.Metod može da zameni sve kljueve sa stringovima. To krši garanciju da je klju  tipa Integer , i budue operacije mogu prouzrokovati izuzetke lošeg kastovanja.Ne možete mnogo šta da uradite sa ovim upozorenjem, osim da ga prouite i da se pitatešta e najverovatnije Jslider  da uradi sa  Dictionary objektom. U našem sluaju, prilino je jasno da Jslider  samo ita informacije, tako da možemo da ignorišemo upozorenje.Razmotrimo sada obrnut sluaj, u kom uzimate objekat osnovnog tipa iz nasleene klase.Možete to pridružiti parametrizovanoj promenljivoj tipa, ali naravno dobiete upozorenje.Na primer,Dictionary labelTable = slider.getLabelTable();

    // UPOZORENJE

    To je u redu – ponovo pogledajte upozorenje i uverite se da etikete matrice zaista sadrže  Integer i  Component   objekte. Naravno, nikad ne postoje apsolutne garancije. Pakosniureaj za kodiranje može da ima instaliran drugiji  Dictionary  u slajderu.  Ali opet,situacija nije gora nego pre JDK-a 5.0. U najgorem sluaju, program e izbaciti izuzetak.Nesrea je što ne možete da iskljuite upozorenja pošto ih uoite. Izgleda nepraktino daisponova gledate svako upozorenje svaki put kada isponova kompilirate sors fajl.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    13/33

    Dizajneri jezika Java su planirali da dodaju fleksibilnije mehnizme upozoravanja ubuduim verzijama JDK-a.

     Zabrane i Ograni enja

    U sledeem odeljku, razmatraemo brojne zabrane koje treba da uzmete u obzir kadradite sa Java genericima. Veina ovih zabrana je posledica brisanja tipa.

     Primitivni Tipovi 

    Ne možete zamenjivati primitivni tip sa parametrom tipa. Stoga, ne postoji Pair samo Pair. Razlog je, naravno, brisanje tipa. Nakon brisanja, klasa Pair   imapolje tipa Object , i možete ga koristiti da uvate double vrednost.Ovo je naravno, muenje, ali je u skladu sa odvojenim statusom primitivnog tipa u jezikuJava. Nije fatalna mana – ima samo osam primitivnih tipova, i uvek možete upravljati

    njima preko odvojenih klasa i metoda kad spoljni tipovi nisu prihvatljiva zamena.

    Upiti Tipa Pri Izvrašavanju

    U virtualnoj mašini objekti uvek imaju specifian negeneriki tip. Zato, svi tipovi upitaproizvode samo izvorni tip. Na primer,

    if (a instanceof Pair) //isto kao a instanceof Pair

    u stvari proverava samo da li a jeste Pair  bilo kog tipa. Isto je tano ispitatiif (a instanceof Pair) // T se ignoriše

    ili kastovanje

    Pair p = (Pair) a; // UPOZORENJE—samo se//testira da li je a Pair 

    Da vas podseti na rizik, dobiete upozorenje kompilatora kad god koristite instanceof   ilikastovanje koje ukljuuje generike tipove.

    U istom duhu, metod getClass uvek vraa izvorni tip. Na primer,

    Pair stringPair = . . .;Pair employeePair = . . .;if (stringPair.getClass() == employeePair.getClass())

    // jednaki su

    Poreenje proizvodi true jer oba poziva od getClass vraaju Pair.class.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    14/33

      Izuzetci

    Ne možete niti izbaciti niti uhvatiti objekte generike klase. U stvari, neispravno je degenerika klasa proširuje Throwable. Na primer, naredna definicija se nee kompilirati:

    public static void doWork(Class t){

    try{do work}catch (T e) // GREŠKA-ne može uhvatiti tip promenljive{

    Logger.global.info(...)}

    Meutim, u redu je koristiti tip promenljivih u specifikaciji izuzetka. Naredni metod jeispravan:public static void doWork(T t)throws T //OK{

    try {do work

    }catch (ThrowablerealCause){

    t.initCause(realCause);throw t;

    }}

     NizoviNe možete deklarisati nizove parametrizovanih tipova, kao što jePair[] table = new Pair(10); //GREŠKA

    Šta nije u redu sa tim? Nakon brisanja, tip od table je Pair[]. Možete ga konvertovati uObject[]:

    Object[] objarray = table;

    Raspravljali smo u Poglavlju 5 da niz pamti tipove svojih komponenti i izbacuje ArrayStoreExeption ako pokušate da smestite element pogrešnog tipa:

    objarray[0] = "Hello"; //GREŠKA-tip komponente je Pair

    Ali brisanje ini ovaj mehanizam neefikasnim za generike tipove. Dodelaobjarray[0] = new Pair();

    e proi proveru za smeštanje u niz ali e ipak proizvesti grešku. Iz tog razloga, nizoviparametrizovanih tipova su zabranjeni.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    15/33

    SAVET: Ako treba da napravite kolekciju objekata parametrizovanog tipa, jednostavno koristite ArrayList: ArrayList< Pair> je sigurno i efektno.

     Instanciranje Generi  kih Tipova

    Ne možete instancirati generi

    ke tipove. Na primer, naredna Pair  konstrukcija jezabranjena:

    public Pair(){ first = new T(); second = new T(); } // GREŠKA

    Brisanje tipa bi promenilo T u Object, a svakako ne želite da pozovete newObject( ).Slino, ne možete napravizi generiki niz:

    public T[] minMax(T[] a){ T[] mm = new T[2]; . . . } // GREŠKA

    Brisanje tipa bi prouzrokovalo da ovaj metod uvek pravi niz Object[2].Ipak, možete konstruisati generike objekte i nizove kroz refleksiju, pozivomClass.newInstance i  Array.newInstance metoda.

    Stati  ki Kontekts

    Ne možete pozivati promenljive tipa u statikim poljima ili metodama. Na primer, mudraideja koja sledi nee raditi:

    public class Singleton

    {public static T getSingleInstance() // GREŠKA

    {if (singleInstance == null)

    construct new instance of  T return singleInstance;}private static T singleInstance; // GREŠKA

    }

    Kad bi ovo moglo da se radi, program bi mogao da deklariše Singleton da delinasumini broj generatora i Singleton da deli dijalog fajl biraa. Ali nemože. Nakon brisanja tipa ostaje samo jedna klasa Singleton, i samo jedno singleInstance  polje. Zbog toga, statika polja i metode sa tipom promenljivih su jednostavno zabranjene.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    16/33

     

    Sukobi Nakon Brisanja

    Zabranjeno je praviti stanja koja prouzrokuju sukobljavanje nakon što su generiki tipoviobrisani. Evo primera. Pretpostavimo da dodamo equals matod klasi Pair na ovaj nain:

    public class Pair{

    public boolean equals(T value){ return first.equals(value) && second.equals(value); }. . .

    }

    Razmotrite Pair. Konceptualno, on ima dva equals metoda:

    boolean equals(String) // definsan u Pair

    boolean equals(Object) // nasleen iz Object

    Ali nas intuicija vue na pogrešnu stranu. Brisanje u metoduboolean equals(T)

     jeboolean equals(Object)

    što se sukobljava sa Object.equals metodom.Lek je, naravno, da promenimo ime metoda koji izaziva sukob.Specifikacija generika navodi drugo pravilo: “ Da bi podržali prevod brisanjem,nameemo ogranienje kojim klasa ili tip promenljive ne smeju biti u isto vremepodtipovi dva tipa interfejsa koji su razliita parametrizacija istog interfejsa.” Na primer,zabranjeno je ovo što sledi:class Calendar implements Comparable { . . . }class GregorianCalendar extends Calendar implementsComparable { . . . }// GREŠKA!!!

    GregorianCalendar   bi tada implementirao oba, i Comparable iComparable, koji su razliita parametrizacija istog interfejsa.Nije najjasnije šta ova zabrana ima sa brisanjem tipa. Negenerika verzija

    class Employee implements Comparable { . . . }class Manager extends Employee implements Comparable{ . . . }

     je dozvoljena.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    17/33

     Pravila Nasle ivanja Za Generi  ke Tipove

    Kada radite sa generikim klasama, morate da nauite nekoliko pravila o nasleivanju ipodtipovima. Ponimo sa situacijom koju mnogi programeri smatraju neintuitivnom.Razmatrajmo klasu i podklasu, kao što su Employee i Manager . Da li je Pair< Manager> 

    podklasa od Pair< Employee >? Iznenaujue možda, ali odgovor je “ne”. Na primer,naredni kod se nee kompiliratiManager[] topHonchos = . . .;Pair = ArrayAlg.minmax(topHonchos); // GREŠKA

    Metod minmax vraa Pair< Manager > , ne Pair< Employee > , i zabranjeno jedodeljivati ih meusobno.Uopšte, ne postoji veza izmeu Pair i Pair , bez obzira kako su S i T povezani(pogledajte sliku 13-1).

    Slika 13-1. Nema naleene veze izmeu para klasa

    Ovo možda izgleda kao stroga zabrana, ali je neophodna radi sigurnosti tipa. Recimo dasmo dozvolili konvertovanje  Pair  u Pair. Razmotrimo ovajkod.Pair managerBuddies = new Pair(ceo, cfo);Pair employeeBuddies = managerBuddies;

    // zabranjeno, ali predpostavimo da nijeemployeeBuddies.setFirst(lowlyEmployee);

    Jasno, poslednji iskaz je ispravan. Ali employeeBuddies i managerBuddies odnose se naisti objekat. Sad smo uspeli da uparimo CFO sa nižim zaposlenim, što ne bi smelo dabude mogue za Pair< Manager >.Sa druge strane, uvek možete konvertovati parametrizovan tip u osnovni tip. Na primer,Pair< Employee > je podtip osnovnog tipa Pair. Ova konverzija je neophodna radipovezivanja sa nasleenim kodom.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    18/33

    Možete li konvertovati u onovni tip i onda prouzrokovati grešku? Na žalost, možete.Razmotrimo sledei primerPair managerBuddies = new Pair(ceo, cfo);Pair rawBuddies = managerBuddies; // OKrawBuddies.setFirst(new File(". . ."));

    // samo upozorenje prilikom kompiliranja 

    Ovo zvui zastrašujue. Meutim, imajte na umu da niste na gorem nego što ste bili sastarijim verzijama Jave. Sigurnost virtualne mašine nije stavljena na kocku. Kada je straniobjekat vraen sa getFirst   i dodeljen promenljivoj  Menager   , izbacuje seClassCastException, kao u dobrim starim danima. Jedino ste izgubili dodatnu sigurnostkoju genriko programiranje normalno obezbeuje.Na kraju, generike klase mogu proširiti ili implementirati druge generike klase. U tompogledu, ne razlikuju se od obinih klasa. Na primer klasa ArrayList može dase konvertuje u List< Employee >. Slika 13-2 prikazuje ovu povazanost.

    Slika13-2. Podtipovska povezanost izmeu generike liste tipova

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    19/33

    “Džoker“ Tipovi

    Ve neko vreme, meu istraživaima sistema tipova, bilo je poznato da je strogi sistemgenerikih tipova prilino nelagodan za korišenje. Java dizajneri su smislili genijalan(ali i pored svega siguran) “otvor za bekstvo”: “džoker” tip. Na primer, „džoker” tip

    Pair

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    20/33

    Pair

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    21/33

      if (min.getBonus() > a[i].getBonus()) min = a[i];if (max.getBonus() < a[i].getBonus()) max = a[i];

    }result.setFirst(min);result.setSecond(max);

    }

    Slika 13-4. “džoker” sa ogranienjem supertipa

    Intuitivno govorei, “džokeri” sa ogranienjem supertipa vam dozvoljavaju da pišete ugenerike objekte, “džokeri” sa ogranienjem podtipa vam dozvoljavaju da itate izgenerikih objekata.Evo još jedne upotrebe ogranienja supertipa. Interfejs Comparable je sam za sebegeneriki tip. Deklarisan je na nain koji sledi:

    public interface Comparable{

    public int compareTo(T other);}

    Ovde, promenljiva tipa ukazuje na tip parametra other . Na primer, klasa String implementira Comparable, i njegov compareTo metod je deklarisan kaopublic int compareTo(String other)

    Ovo je lepo – izriit parametar ima ispravan tip. Pre JDK-a 5.0 , other  je bio Object , i bilo je neophodno kastovanje u implementaciji metoda.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    22/33

    Zato što je Comparable generikog tipa, možda je trebalo da odradimo bolji posao sametodom min klase ArryAlg? Mogli smo da ga deklarišemo kaopublic static T min(T[] a) . . .

    Ovo izgleda mnogo detaljnije nego korišenje samo T extends Comparable, i radilobi lepo za mnoge klase. Na primer, ako izraunavate minimum niza String, onda je T tipaString, i String  je podtip od Comparable. Ali emo naleteti na problem kadaobraujemo niz GregorianCalendar   objekata. Ono što se dešava je da jeGregorianCalendar   podklasa od Calendar   , i Calendar implementiraComparable. Prema tome, GregorianCalendar   implementiraComparable ali ne Comparable.U situaciji kao što je ova, supertipovi dolaze u pomo:

    public static .  Na prvipogled, ovo izgleda identino osnovnom Pair   tipu. U stvari, tipovi se veoma razlikuju.Tip Pair ima metod kao što je? getFirst()

    void setFirst(?)

    Povratna vrednost od getFirst  može biti dodeljena jedino Object -u. Metod setFirst   nemože biti pozvan nikada, ak ni sa Object -om. To je suštinska razlika izmeu Pair iPair; možete pozvati setObject   metod osnovne Pair  klase sa bilo kojim Object -om.Zašto biste ikada želeli tako slabašan tip? Koristan je za veoma jednostavne operacije. Naprimer, naredni metod ispituje da li par sadrži dati objekat. Nikad nije potreban stvarnitip.

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    23/33

    public static boolean hasNulls(Pair p){

    return p.getFirst() == null || p.getSecond() == null;}

    Mogli ste da izbegnete tip “džoker” pretvarajui njegov sadržaj u generiki method:public static boolean hasNulls(Pair p)

    meutim, verzija sa tipom “džoker” izgleda lakše za itanje.

     Hvatanje “Džokera”  

    Hajde da napišemo metod koji zamenjuje mesta elementima para:

    public static void swap(Pair p)

    “Džoker” nije tip promenljive, tako da ne možemo da napišemo kod koji koristi ? kao tip.Drugim reima, neispravno je sledee:

    ? t = p.getFirst(); // GREŠKAp.setFirst(p.getSecond());p.setSecond(t);

    To je problem jer nam treba da privremeno sauvamo prvi element dok im zamenjujemomesta. Sreom, postoji interesantno rešenje tog problema. Možemo napisati pomonimetod, swapHelper , na ovaj nain:public static void swapHelper(Pair p)

    { T t = p.getFirst();p.setFirst(p.getSecond());p.setSecond(t);

    }

    Primetimo da je swapHelper  generiki metod, dok swap nije - ima fiksne parametre tipaPair. Sada možemo pozvati swapHelper  iz swap-a:public static void swap(Pair p) { swapHelper(p); }

    u ovom sluaju, parametr T iz metoda swapHelper   hvata “džokera”. Nije jasno koje

    tipove “džoker” nazna

    ava, ali to je odre

    en tip, i definicija swapHelper   savršenoima smisla kad T naznaava taj tip.Naravno, u ovom sluaju, nismo bili primorani da koristimo “džokera” – nema ništa lošeu korišenju parametra tipa, kao u swapHelper   metodu. Meutim, razmotrimo ovajprimer u kome se tip “džoker” javlja u sred izraunavanja:public static void maxMinBonus(Manager[] a, Pair

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    24/33

      PairAlg.swapHelper(result);// OK--swapHelper hvata tip “džoker”}

    Ovde, “džokerov” mehanizam za hvatanje se ne može izbei.Hvatanje “džokera” je jedino ispravno u veoma ogranienim okolnostima. Kompilatormora biti sposoban da garantuje da je “džoker” jedan, odreen tip. Na primer, T u ArrayList

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    25/33

     40. if (max.getBonus() < a[i].getBonus()) max = a[i];41. }42. result.setFirst(min);43. result.setSecond(max);44. }45.46. public static void maxMinBonus(Manager[] a, Pair p)56. {57. return p.getFirst() == null || p.getSecond() == null;

    58. }59.60. public static void swap(Pair p) { swapHelper(p); }61.62. public static void swapHelper(Pair p)63. {64. T t = p.getFirst();65. p.setFirst(p.getSecond());66. p.setSecond(t);67. }68. }69.70. class Employee71. {72. public Employee(String n, double s, int year, int month, intday)73. {74. name = n;75. salary = s;76. GregorianCalendar calendar = new GregorianCalendar(year,month - 1, day);77. hireDay = calendar.getTime();78. }79.80. public String getName()81. {82. return name;

    83. }84.85. public double getSalary()86. {87. return salary;88. }89.90. public Date getHireDay()91. {92. return hireDay;

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    26/33

     93. }94.95. public void raiseSalary(double byPercent)96. {97. double raise = salary * byPercent / 100;98. salary += raise;99. }

    100.101. private String name;102. private double salary;103. private Date hireDay;104. }105.106. class Manager extends Employee107. {108. /**109. @parametar n ime zaposlenog110. @parametar s plata111. @parametar year godina zaposlenja112. @parametar month mesec zaposlenja

    113. @parametar day dan zaposlenja114. */115. public Manager(String n, double s, int year, int month, int day)116. {117. super(n, s, year, month, day);118. bonus = 0;119. }120.121. public double getSalary()122. {123. double baseSalary = super.getSalary();124. return baseSalary + bonus;125. }126.127. public void setBonus(double b)128. {129. bonus = b;130. }131.132. public double getBonus()133. {134. return bonus;135. }136.137. private double bonus;138. }

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    27/33

     Refleksija I Generici 

    Klasa Class je sada generika. Na primer String.class je u stvari objekat (u stvari, jediniobjekat) klase Class.Parametar tipa je koristan jer dozvoljava da metodi od Class  budu odreeniji po

    pitanju njihovih povratnih tipova. Sledeu metodi u Class  koriste prednostiparametra tipa:

    T newInstance()T cast(Object obj)T[] getEnumConstants()Class

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    28/33

     

     java.lang.reflect.Constructor 1.1

    •  T newInstance(Object... parameters) 5.0

    Vraa novu instancu napravljenu sa datim parametrima.

     Koriš  enje Class Parametara za Slaganje Tipa 

    Ponekad je korisno složiti tipove promenljive od Class parametra u generikommetodu. Evo kanonskog primera:public static Pair makePair(Class c) throwsInstantiationException,IllegalAccessException

    {return new Pair(c.newInstance(), c.newInstance());

    }

    Ako pozovete

    makePair(Employee.class)

    tada  Employee.class  je objekat tipa  Class. Parametar tipa T od makePair  metode se slaže sa  Employee, i kompilator može da zakljui da metod vraaPair.

     Informacije o Generi  kom Tipu U Virtualnoj Mašini 

    Jedna od primetnih karakteristika Java generika je brisanje generikih tipova u virtualnojmašini. Možda iznenaujue, obrisane klase i dalje uvaju bledo seanje na svojegeneriko poreklo. Na primer, izvorna klasa Pair   zna da potie od generike klase Pair, iako objekat tipa Pair  ne može rei da li je konstruisan kao Pair  iliPair< Employee>.Slino, uzmimo metodpublic static Comparable min(Comparable[] a)

    koji je brisanje generikog metodapublic static

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    29/33

    Drugim reima, možete da rekonstruišete sve o generikim klasama i metodama što sunjihovi implementatori deklarisali. Meutim, neete znati kako je razrešen tip parametaraza konkretne objekte ili pozive metoda.NAPOMENA: 

    Informacija o tipu koja je sadržana u klasnom fajlu da omogui refleksiju generika jenekompatibilna sa starijim virtualnim mašinama.

    Da bi iskazao deklaracije generikog tipa, JDK 5.0 je stvorio novi interfejs Type  u java.lang.reflect  paketu. Interfejs ima sledee podtipove:

    •  Klasu Class, opisuje konkretne tipove•  Interfejs TypeVariable, opisuje promenljive tipa (kao što je T  extend

    Comparable

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    30/33

     Primer 13-4: GenericReflectionTest.java

    1. import java.lang.reflect.*;2. import java.util.*;

    3.4. public class GenericReflectionTest5. {6. public static void main(String[] args)7. {8. // read class name from command-line args or user input9. String name;10. if (args.length > 0)11. name = args[0];12. else13. {14. Scanner in = new Scanner(System.in);15. System.out.println("Enter class name (e.g.java.util.Date): ");

    16. name = in.next();17. }18.19. try20. {21. // print generic info for class and public methods22. Class cl = Class.forName(name);23. printClass(cl);24. for (Method m : cl.getDeclaredMethods())25. printMethod(m);26. }27. catch (ClassNotFoundException e)28. {

    29. e.printStackTrace();30. }31. }32.33. public static void printClass(Class cl)34. {35. System.out.print(cl);36. printTypes(cl.getTypeParameters(), "");37. Type sc = cl.getGenericSuperclass();38. if (sc != null)39. {40. System.out.print(" extends ");41. printType(sc);42. }

    43. printTypes(cl.getGenericInterfaces(), " implements ", ", ","");44. System.out.println();45. }46.47. public static void printMethod(Method m)48. {49. String name = m.getName();50. System.out.print(Modifier.toString(m.getModifiers()));

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    31/33

     51. System.out.print(" ");52. printTypes(m.getTypeParameters(), " ");53.54. printType(m.getGenericReturnType());55. System.out.print(" ");56. System.out.print(name);57. System.out.print("(");

    58. printTypes(m.getGenericParameterTypes(), "", ", ", "");59. System.out.println(")");60. }61.62. public static void printTypes(Type[] types, String pre, Stringsep, String suf)63. {64. if (types.length > 0) System.out.print(pre);65. for (int i = 0; i < types.length; i++)66. {67. if (i > 0) System.out.print(sep);68. printType(types[i]);69. }

    70. if (types.length > 0) System.out.print(suf);71. }72.73. public static void printType(Type type)74. {75. if (type instanceof Class)76. {77. Class t = (Class) type;78. System.out.print(t.getName());79. }80. else if (type instanceof TypeVariable)81. {82. TypeVariable t = (TypeVariable) type;83. System.out.print(t.getName());84. printTypes(t.getBounds(), " extends ", " & ", "");85. }86. else if (type instanceof WildcardType)87. {88. WildcardType t = (WildcardType) type;89. System.out.print("?");90. printTypes(t.getLowerBounds(), " extends ", " & ", "");91. printTypes(t.getUpperBounds(), " super ", " & ", "");92. }93. else if (type instanceof ParameterizedType)94. {95. ParameterizedType t = (ParameterizedType) type;96. Type owner = t.getOwnerType();

    97. if (owner != null) { printType(owner);System.out.print("."); }98. printType(t.getRawType());99. printTypes(t.getActualTypeArguments(), "");100. }101. else if (type instanceof GenericArrayType)102. {103. GenericArrayType t = (GenericArrayType) type;104. System.out.print("");105. printType(t.getGenericComponentType());

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    32/33

    106. System.out.print("[]");107. }108.109. }110. }

     java.lang.Class 1.0

    •  TypeVariable[] getTypeParameters() 5.0

    dobija generike promenljive tipa ako je taj tip deklarisan kao generiki tip, ili nizdužine 0 inae.

    •  Type getGenericSuperclass() 5.0

    dobija generiki tip superklase koji je deklarisan za ovaj tip, ili null ako je ovaj tipObject  ili nije klasni tip

    •  Type[] getGenericInterfaces() 5.0

    dobija generike tipove interfejsa koji su deklarisani za ovaj tip, redom kojim sudeklarisani, ili niz dužine 0 ako ovaj tip ne implementira interfejse.

     java.lang.reflect.Method 1.1

    •  TypeVariable[] getTypeParameters() 5.0

    dobija generike promenljive tipa ako je ovaj metod deklarisan kao generiki metodili niz dužine 0 inae.•  Type getGenericReturnType() 5.0

    dobija generiki povratni tip sa kojim je ovaj metod deklarisan.•

     

    Type[] getGenericParameterTypes() 5.0dobija generike parametre tipova sa kojim je ovaj metod deklarisan, ako metodnema parametre, vraen je niz dužine 0.

     java.lang.reflect.TypeVariable 5.0

  • 8/19/2019 C Documents and Settings Peofesional Application Data Opera Opera Profile Cache4 Opr00VUE

    33/33

    •  String getName()

    Dobija ime ovog promenljive tipa•  Type[] getBounds()

    Dobija ogranienje podklasa ovog tipa promenljive, ili niz dužine 0 ako je promenljivaneograniena.

     java.lang.reflect.WildcardType 5.0

    •  Type[] getLowerBounds()

    Dobija podklasna (extends) ogranienja ove promenljive tipa, ili niz dužine 0 akonema ogranienja podklasa.•  Type[] getUpperBounds()

    Dobija superklasna (super ) ogranienja ove promenljive tipa, ili niz dužine 0 akonema ogranienja superklasa.

     java.lang.reflect.ParameterizedType 5.0

    •  Type getRawType()

    Dobija izvorni tip ovog parametrizovanog tipa.•  Type[] getActualTypeArguments()

    Dobija parametre tipa sa kojima je ovaj parametrizovani tip deklarisan.•  Type getOwnerType()

    Dobija spoljašnji klasni tip ako je ovo unutrašnji tip, ili null ako je ovo tip najvišegnivoa.

     java.lang.reflect.GenericArrayType 5.0

    •  Type getGenericComponentType()Dobija tip generike komponente sa kojom je ovaj nizovni tip deklarisan.

    Sada ste stigli do kraja prvog toma knjige Core Java. Ovaj tom pokriva osnove Javaprogramskog jezika i deo standardne biblioteke koja vam treba za veinu programerskihprojekata. Nadamo se da ste uživali u prolazu kroz osnove Jave i da ste usput pronašlikorisne informacije. Za naprednije teme, kao što je rad u mrežnom okruženju , multithreading, sigurnost, i internacionalizacija, molim vas obratite se drugom tomu.