Java 5 je v jezik Java prinesel generike. V tem članku vam predstavim generike in razpravljam o generičnih vrstah, generičnih metodah, generikih in sklepanju na tipe, generičnih polemikah ter generikih in onesnaževanju kupa.
prenos Prenesite kodo Prenesite izvorno kodo za primere v tej vadnici Java 101. Ustvaril Jeff Friesen za JavaWorld.Kaj so generiki?
Generiki so zbirka sorodnih jezikovnih lastnosti, ki omogočajo, da tipi ali metode delujejo na objektih različnih vrst, hkrati pa zagotavljajo varnost tipa prevajalskega časa. Generične funkcije obravnavajo problem java.lang.ClassCastException
vrženi med izvajanjem, ki so rezultat kode, ki ni varna za tip (tj. predvajanje predmetov iz njihovih trenutnih tipov v nezdružljive vrste).
Generiki in ogrodje zbirk Java
Generiki se pogosto uporabljajo v okviru Java Collections Framework (uradno predstavljeni v prihodnosti Java 101 članki), vendar zanjo niso izključni. Generiki se uporabljajo tudi v drugih delih Javine knjižnice standardnih razredov, vključno z java.lang.Class
, java.lang.Primerljivo
, java.lang.ThreadLocal
, in java.lang.ref.WeakReference
.
Razmislite o naslednjem fragmentu kode, ki dokazuje pomanjkanje varnosti tipa (v okviru okvira Java Collections Framework java.util.LinkedList
class), ki je bila pogosta v kodi Java pred uvedbo generičnih zdravil:
Seznam doubleList = nov LinkedList (); doubleList.add (novo Double (3.5)); Double d = (Double) doubleList.iterator (). Next ();
Čeprav je cilj zgornjega programa le shranjevanje java.lang.Dvojnik
predmetov na seznamu, nič ne preprečuje shranjevanja drugih vrst predmetov. Lahko na primer določite doubleList.add ("Pozdravljeni");
da dodate a java.lang.String
predmet. Pri shranjevanju druge vrste predmeta, končne vrstice (Dvojno)
vzroki operaterja zasedbe ClassCastException
biti vržen, ko se sooči zDvojno
predmet.
Ker tega pomanjkanja varnosti tipa zaznamo šele med izvajanjem, se razvijalec morda ne zaveda težave in prepusti odjemalcu (namesto prevajalniku), da odkrije. Generiki pomagajo prevajalniku opozoriti razvijalca na težavo shranjevanja predmeta z ne-Dvojno
vnesite na seznam tako, da razvijalcu dovolite, da ga označi kot samo vsebuje Dvojno
predmetov. Ta pomoč je prikazana spodaj:
Seznam doubleList = nov LinkedList (); doubleList.add (novo Double (3.5)); Double d = doubleList.iterator (). Next ();
Seznam
zdaj se glasi "Seznam
od Dvojno
.” Seznam
je generični vmesnik, izražen kot Seznam
, kar traja Dvojno
argument tipa, ki je prav tako določen pri ustvarjanju dejanskega predmeta. Prevajalnik lahko zdaj uveljavi pravilnost tipa pri dodajanju predmeta na seznam - seznam lahko na primer shrani Dvojno
samo vrednosti. To izvrševanje odpravlja potrebo po (Dvojno)
igralska zasedba.
Odkrivanje generičnih vrst
A generični tip je razred ali vmesnik, ki uvede nabor parametriziranih tipov prek a seznam parametrov formalnega tipa, ki je ločen z vejicami seznam imen parametrov tipa med dvema kotnima oklepajema. Splošni tipi se držijo naslednje skladnje:
razred identifikator<formalTypeParameterList> {// class body} vmesnik identifikator<formalTypeParameterList> {// telo vmesnika}
Okvir Java Collections Framework ponuja veliko primerov generičnih tipov in njihovih seznamov parametrov (in nanje se sklicujem v tem članku). Na primer, java.util.Set
je generična vrsta, je njegov formalni seznam parametrov tipa in
E
je samotni tip parametra na seznamu. Drug primer jejava.util.Map
.
Dogovor o poimenovanju parametrov tipa Java
Konvencija o programiranju Java narekuje, da so imena parametrov tipa ene velike črke, na primer A parametriziran tip je primerek generičnega tipa, pri katerem so parametri tipa generičnega tipa nadomeščeni z dejanski argumenti tipa (imena vrst). Na primer, Jezik Java podpira naslednje vrste dejanskih argumentov tipa: Vsaka generična vrsta pomeni obstoj a surov tip, ki je generični tip brez formalnega seznama parametrov tipa. Na primer, Razglasitev generičnega tipa vključuje določitev formalnega seznama parametrov tipa in dostop do teh parametrov tipa skozi njegovo izvajanje. Uporaba generičnega tipa vključuje posredovanje dejanskih argumentov tipa njegovim parametrom tipa, ko ustvari generični tip. Glej seznam 1. Seznam 1 prikazuje generično deklaracijo in uporabo v kontekstu preprostega tipa vsebnika, ki hrani predmete ustrezne vrste argumenta. Da bo koda preprosta, sem izpustil preverjanje napak. The The Sestavi seznam 1 ( Upoštevajte pa, da v tem primeru ni mogoče kršiti varnosti tipa. Preprosto ni mogoče shraniti Izvedite The Včasih boste želeli omejiti vrste dejanskih argumentov tipa, ki jih lahko posredujete parametru tipa. Na primer, morda želite omejiti, da parameter tipa sprejema samo Parameter tipa lahko omejite tako, da podate Zgornja meja, ki je tip, ki služi kot zgornja meja za tipe, ki jih je mogoče prenesti kot dejanske argumente tipa. Z rezervirano besedo določite zgornjo mejo Na primer, Parametru tipa lahko dodelite več kot eno zgornjo mejo. Vendar mora biti prva vezava vedno razred, dodatne meje pa vedno vmesniki. Vsaka vezava je od predhodnika ločena z znakom ( Seznam 2 The The Sestavi seznam 2 ( Za parameter generičnega tipa ne morete podati spodnje meje. Da bi razumeli, zakaj priporočam, da preberete pogosta vprašanja o Javni generiki Angelike Langer na temo spodnjih meja, za katere pravi, da bi bile "zmedene in ne posebej koristne". Recimo, da želite natisniti seznam predmetov, ne glede na to, ali so ti predmeti nizi, zaposleni, oblike ali druge vrste. Vaš prvi poskus je lahko videti tako, kot je prikazano na seznamu 3. Zdi se logično, da je seznam nizov ali seznam celih števil podvrsta seznama predmetov, vendar se prevajalnik pritožuje, ko poskušate sestaviti ta seznam. Natančneje, pove vam, da seznama nizov ni mogoče pretvoriti v seznam predmetov in podobno za seznam celih števil. Sporočilo o napaki, ki ste ga prejeli, je povezano s temeljnim pravilom generikov:E
za element, K
za ključ, V
za vrednost in T
za tip. Če je mogoče, se izogibajte uporabi nesmiselnega imena, kot je P
— java.util.List
pomeni seznam elementov, toda kaj bi lahko mislili z Seznam
Nastavite
je parametriziran tip, kjer Vrvica
je dejanski argument tipa, ki nadomešča parameter tipa E
.Seznam
, Žival
je posredovano E
.Nastavite
, Seznam
je posredovano E
.Zemljevid
, Vrvica
je posredovana K
in Vrvica[]
je posredovano V
.class Container {Set elements; }
, E
je posredovano E
.?
) se posreduje parametru tipa. Na primer, v Razred
, ?
je posredovano T
.Razred
je surova vrsta za Razred
. V nasprotju s splošnimi vrstami se surove vrste lahko uporabljajo s kakršnimi koli predmeti.Izjava in uporaba generičnih vrst v Javi
Seznam 1:
GenDemo.java
(različica 1)class Container {private E [] elementi; zasebni indeks int; Vsebnik (int size) {elements = (E []) new Object [size]; indeks = 0; } void add (E element) {elements [index ++] = element; } E get (int index) {return elementi [indeks]; } int size () {indeks vrnitve; }} javni razred GenDemo {public static void main (String [] args) {Container con = new Container (5); con.add ("sever"); con.add ("Jug"); con.add ("vzhod"); con.add ("Zahod"); for (int i = 0; i <con.size (); i ++) System.out.println (con.get (i)); }}
Zabojnik
razred razglasi, da je generičen tip z določitvijo seznam parametrov formalnega tipa. Vnesite parameter
E
se uporablja za identifikacijo vrste shranjenih elementov, elementa, ki ga je treba dodati notranjemu polju, in vrste vrnitve pri pridobivanju elementa.Posoda (int velikost)
konstruktor ustvari matriko prek elementi = (E []) nov objekt [velikost];
. Če se sprašujete, zakaj nisem navedel elementi = novi E [velikost];
, razlog je, da to ni mogoče. S tem bi lahko prišlo do ClassCastException
.javac GenDemo.java
). The (E [])
cast povzroči, da prevajalnik prikaže opozorilo o tem, da oddaja ni potrjena. Označuje možnost, da spuščanje iz Predmet []
do E []
lahko krši varnost tipa, ker Predmet []
lahko shrani katero koli vrsto predmeta.E
objekt v notranjem polju. Predpona Posoda (int velikost)
konstruktor z @SuppressWarnings ("nepreverjeno")
bi potisnil to opozorilno sporočilo.java GenDemo
za zagon te aplikacije. Upoštevati morate naslednje rezultate:sever jug vzhod zahod
Omejevalni parametri tipa v Javi
E
v Nastavite
je primer neomejeni tip parametra ker lahko posredujete kateri koli dejanski argument tipa E
. Lahko na primer določite Nastavite
, Nastavite
, ali Nastavite
.Zaposleni
in njegovih podrazredih.podaljša
čemur sledi ime tipa zgornje meje.razred Zaposleni
omejuje vrste, na katere je mogoče prenesti Zaposleni
do Zaposleni
ali podrazred (npr. Računovodja
). Določanje novi zaposleni
bi bilo zakonito, medtem ko novi zaposleni
bi bilo nezakonito.&
). Oglejte si seznam 2.Seznam 2:
GenDemo.java
(različica 2)uvoz java.math.BigDecimal; uvoz java.util.Arrays; abstraktni tečaj Zaposleni {private BigDecimal hourlySalary; ime zasebnega niza; Zaposleni (ime niza, BigDecimal hourlySalary) {this.name = name; this.hourlySalary = urna plača; } public BigDecimal getHourlySalary () {return hourlySalary; } javni niz getName () {return ime; } javni String toString () {return ime + ":" + hourlySalary.toString (); }} class Accountant extends Zaposleni implementira Comparable {Accountant (String name, BigDecimal hourlySalary) {super (name, hourlySalary); } public int compareTo (Accountant acct) {return getHourlySalary (). compareTo (acct.getHourlySalary ()); }} razred SortedE Employees
Zaposleni
razred povzema koncept zaposlenega, ki prejema urno plačo. Ta razred je podrazvrščen z Računovodja
, ki tudi izvaja Primerljivo
da to označi Računovodja
s lahko primerjamo glede na njihov naravni red, ki je v tem primeru urna plača.java.lang.Primerljivo
vmesnik je razglašen kot generični tip z imenom enega samega parametra tipa T
. Ta vmesnik ponuja int compareTo (T o)
metoda, ki primerja trenutni objekt z argumentom (tipa T
), vrne negativno celo število, nič ali pozitivno celo število, saj je ta objekt manjši od, enak ali večji od določenega predmeta.SortiranoZaposleni
razred vam omogoča shranjevanje Zaposleni
primerki podrazreda, ki se izvajajo Primerljivo
v notranjem polju. Ta matrika je razvrščena (prek java.util.Arrays
razreda void sort (Object [] a, int fromIndex, int toIndex)
razredna metoda) v naraščajočem vrstnem redu urne postavke po Zaposleni
doda se primerek podrazreda.javac GenDemo.java
) in zaženite aplikacijo (java GenDemo
). Upoštevati morate naslednje rezultate:George Smith: 15.20 Jane Jones: 25.60 John Doe: 35.40
Spodnje meje in splošni parametri tipa
Glede na nadomestne znake
Seznam 3:
GenDemo.java
(različica 3)uvoz java.util.ArrayList; uvoz java.util.Iterator; uvoz java.util.List; javni razred GenDemo {public static void main (String [] args) {Seznam navodil = new ArrayList (); direction.add ("sever"); direction.add ("jug"); direction.add ("vzhod"); direction.add ("zahod"); printList (navodila); Seznam ocen = novo ArrayList (); grade.add (novo celo število (98)); grade.add (novo celo število (63)); grade.add (novo celo število (87)); printList (ocene); } static void printList (seznam seznam) {Iterator iter = list.iterator (); while (iter.hasNext ()) System.out.println (iter.next ()); }}