c documents and settings peofesional application data opera opera profile cache4 opr00vue
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.