Java 5 toi geneeriset tiedot Java-kielelle. Tässä artikkelissa esitän sinulle geneerisiä aineita ja keskustelen geneerisistä tyyppeistä, geneerisistä menetelmistä, geneerisistä aineista ja tyyppipäätöksistä, geneerisistä kiistoista sekä geneerisistä aineista ja kasan pilaantumisesta.
lataa Hanki koodi Lataa lähdekoodi esimerkkejä tästä Java 101 -oppaasta. Luonut Jeff Friesen JavaWorldille.Mitä ovat geneeriset lääkkeet?
Yleiset ovat joukko toisiinsa liittyviä kieliominaisuuksia, joiden avulla tyypit tai menetelmät voivat toimia erityyppisissä kohteissa ja samalla tarjota käännösajan tyyppisen turvallisuuden. Yleisillä ominaisuuksilla käsitellään java.lang.ClassCastException
Ne heitetään ajon aikana, jotka ovat seurausta koodista, joka ei ole tyyppiturvallinen (eli esineiden heittäminen nykyisistä tyypeistään yhteensopimattomiin tyyppeihin).
Generics ja Java Collections Framework
Geneerisiä aineita käytetään laajalti Java Collections Frameworkissa (otetaan virallisesti käyttöön tulevaisuudessa Java 101 artikkelit), mutta ne eivät ole yksinomaan sitä. Geneerisiä aineita käytetään myös muualla Java-vakioluokan kirjastossa java.lang.luokka
, java.lang.Vertailukelpoinen
, java.lang.ThreadLocal
ja java.lang.ref.WeakReference
.
Harkitse seuraavaa koodinpätkää, joka osoittaa tyyppiturvallisuuden puutteen (Java Collections Frameworkin yhteydessä) java.util.LinkedList
luokka), joka oli yleistä Java-koodissa ennen geneeristen lääkkeiden käyttöönottoa:
Lista doubleList = uusi LinkedList (); doubleList.add (uusi Double (3.5)); Tupla d = (Tupla) doubleList.iterator (). Seuraava ();
Vaikka yllä olevan ohjelman tavoitteena on tallentaa vain java.lang.Tupla
luettelossa olevia objekteja, mikään ei estä muunlaisten objektien tallentamista. Voit esimerkiksi määrittää doubleList.add ("Hei");
lisätä a java.lang.String
esine. Kun kuitenkin varastoidaan toisenlaista esinettä, viimeinen rivi (Kaksinkertainen)
valukäyttäjä aiheuttaa ClassCastException
heitettävä joutuessaan kohtaamaanKaksinkertainen
esine.
Koska tämä tyyppiturvallisuuden puute havaitaan vasta ajon aikana, kehittäjä ei ehkä ole tietoinen ongelmasta ja jättää sen asiakkaan (kääntäjän sijasta) löydettäväksi. Yleisohjeet auttavat kääntäjää varoittamaan kehittäjää ongelmasta, joka liittyy objektin tallentamiseen muuhun kuinKaksinkertainen
kirjoita luetteloon antamalla kehittäjän merkitä luettelo vain sisältäväksi Kaksinkertainen
esineitä. Tämä apu on osoitettu alla:
Lista doubleList = uusi LinkedList (); doubleList.add (uusi Double (3.5)); Tupla d = doubleList.iterator (). Seuraava ();
Lista
lukee nytLista
/ Kaksinkertainen
.” Lista
on yleinen käyttöliittymä ilmaistuna muodossa Lista
, joka vie a Kaksinkertainen
type-argumentti, joka määritetään myös varsinaisen objektin luomisessa. Kääntäjä voi nyt pakottaa tyypin oikeellisuuden lisäämällä objektia luetteloon - esimerkiksi luettelo voi tallentaa Kaksinkertainen
vain arvot. Tämä täytäntöönpano poistaa tarpeen (Kaksinkertainen)
heittää.
Yleisten tyyppien löytäminen
A yleinen tyyppi on luokka tai käyttöliittymä, joka esittelee parametrisoitujen tyyppien joukon a: n kautta muodollinen tyypin parametriluettelo, joka on pilkulla erotettu luettelo tyypin parametrien nimistä kulmasulkeiden parin välillä. Yleiset tyypit noudattavat seuraavaa syntaksia:
luokassa tunniste<formalTypeParameterList> {// class body} -käyttöliittymä tunniste<formalTypeParameterList> {// käyttöliittymän runko}
Java Collections Framework tarjoaa monia esimerkkejä yleistyypeistä ja niiden parametriluetteloista (ja viittaan niihin tässä artikkelissa). Esimerkiksi, java.util.Set
on yleinen tyyppi, on sen muodollinen tyyppiparametriluettelo ja
E
on luettelon yksinäinen tyypin parametri. Toinen esimerkki onjava.util.Kartta
.
Java-tyypin parametrien nimeämiskäytäntö
Java-ohjelmointikäytäntö määrää, että tyypin parametrien nimet ovat yksittäisiä isoja kirjaimia, kuten A parametrisoitu tyyppi on yleinen tyypin esiintymä, jossa yleisen tyypin tyypin parametrit korvataan todelliset tyypin argumentit (tyyppinimet). Esimerkiksi, Java-kieli tukee seuraavanlaisia todellisia tyyppiargumentteja: Jokainen yleinen tyyppi tarkoittaa a: n olemassaoloa raaka tyyppi, joka on yleinen tyyppi ilman muodollista tyyppiparametriluetteloa. Esimerkiksi, Yleisen tyypin ilmoittaminen edellyttää muodollisen tyyppiparametriluettelon määrittämistä ja pääsyä näihin tyyppiparametreihin koko toteutuksen ajan. Yleisen tyypin käyttäminen edellyttää, että todelliset tyyppiargumentit välitetään sen tyyppiparametreille, kun yleistyyppiä selvitetään. Katso luettelo 1. Listaus 1 osoittaa yleisen tyypin ilmoituksen ja käytön yksinkertaisen säilötyypin yhteydessä, joka tallentaa sopivan argumenttityypin objektit. Koodin yksinkertaisuuden vuoksi olen jättänyt virheen tarkistuksen pois. Koosta luettelo 1 ( Huomaa kuitenkin, että tässä esimerkissä ei voida mitenkään rikkoa tyyppiturvallisuutta. Ei yksinkertaisesti ole mahdollista tallentaa Suorittaa Joskus haluat rajoittaa tyypin todellisten argumenttien tyyppejä, jotka voidaan välittää tyypin parametrille. Esimerkiksi, haluat ehkä rajoittaa tyypin parametrin hyväksymään vain Voit rajoittaa tyypin parametria määrittämällä yläraja, joka on tyyppi, joka toimii ylärajana tyyppeille, jotka voidaan välittää todellisina tyyppiargumentteina. Määritä yläraja varatulla sanalla Esimerkiksi, Voit määrittää tyypin parametrille useamman kuin yhden ylärajan. Ensimmäisen sidoksen on kuitenkin aina oltava luokka, ja lisärajoitusten tulee aina olla rajapintoja. Jokainen sidos erotetaan edeltäjäänsä tähdellä ( Listaus 2 Koosta luettelo 2 ( Et voi määrittää yleistä tyypin parametrin alarajaa. Ymmärtääkseni, miksi suosittelen lukemaan Angelika Langerin Java Genericsin usein kysytyt kysymykset alarajoista, jotka hänen mukaansa "olisivat hämmentäviä eikä erityisen hyödyllisiä". Oletetaan, että haluat tulostaa luettelon objekteista riippumatta siitä, ovatko nämä merkkijonot, työntekijät, muodot vai jonkin muun tyyppisiä. Ensimmäinen yrityksesi saattaa näyttää siltä, mikä näkyy luettelossa 3. Vaikuttaa loogiselta, että merkkijonoluettelo tai kokonaislukujen luettelo on objektiluettelon alatyyppi, mutta kääntäjä valittaa, kun yrität koota tätä luetteloa. Tarkemmin sanottuna se kertoo, että merkkijonoluetteloa ei voida muuntaa objektiluetteloksi, ja vastaavasti kokonaislukulistalle. Saamasi virheilmoitus liittyy geneeristen lääkkeiden perussääntöön:E
elementille, K
avaimelle, V
arvolle ja T
tyypille. Vältä mahdollisuuksien mukaan merkityksettömän nimen, kuten P
— java.util.List
tarkoittaa luetteloa elementeistä, mutta mitä voisit tarkoittaa tällä Lista
Aseta
on parametrisoitu tyyppi missä Merkkijono
on todellinen tyyppi-argumentti, joka korvaa tyypin parametrin E
.Lista
, Eläin
siirretään E
.Aseta
, Lista
siirretään E
.Kartta
, Merkkijono
siirretään K
ja Merkkijono []
siirretään V
.luokka Container {Set elements; }
, E
siirretään E
.?
) välitetään tyypin parametrille. Esimerkiksi Luokka
, ?
siirretään T
.Luokka
on raaka tyyppi Luokka
. Toisin kuin yleiset tyypit, raakatyyppejä voidaan käyttää minkä tahansa kohteen kanssa.Yleisten tyyppien ilmoittaminen ja käyttö Java-käyttöjärjestelmässä
Listaus 1:
GenDemo.java
(versio 1)luokka Container {private E [] -elementit; yksityinen int-indeksi; Container (int size) {elements = (E []) new Object [size]; indeksi = 0; } void add (E-elementti) {elements [index ++] = elementti; } E get (int index) {return elementit [index]; } int koko () {paluuindeksi; }} public class GenDemo {public static void main (String [] argumentit) {Container con = uusi Container (5); jatko ("pohjoinen"); jatko ("etelä"); con.add ("itä"); jatko ("länsi"); for (int i = 0; i <koko. (); i ++) System.out.println (con.get (i)); }}
Kontti
luokka ilmoittaa olevansa yleinen tyyppi määrittelemällä muodollinen tyypin parametriluettelo. Tyyppi-parametri
E
käytetään tunnistamaan tallennettujen elementtien tyyppi, sisäiseen ryhmään lisättävä elementti ja palautustyyppi elementtiä noudettaessa.Kontti (sis. Koko)
konstruktori luo matriisin kautta elementit = (E []) uusi objekti [koko];
. Jos mietit, miksi en määrittänyt elementit = uusi E [koko];
, syy on se, että se ei ole mahdollista. Se voi johtaa a ClassCastException
.javac GenDemo.java
). (E [])
cast saa kääntäjän antamaan varoituksen valinnan estämisestä. Se merkitsee mahdollisuutta, että downcasting from Esine[]
että E []
saattaa rikkoa tyyppiturvallisuutta, koska Esine[]
voi tallentaa minkä tahansa tyyppisen objektin.E
objekti sisäisessä taulukossa. Etuliite Kontti (sis. Koko)
rakentaja kanssa @SuppressWarnings ("tarkistamaton")
tukahduttaisi tämän varoitusviestin.java GenDemo
tämän sovelluksen suorittamiseksi. Ota huomioon seuraava tulos:pohjoinen Etelä Itä Länsi
Rajoittavat tyypin parametrit Java-ohjelmassa
E
sisään Aseta
on esimerkki rajoittamaton tyypin parametri koska voit välittää minkä tahansa todellisen tyypin argumentin E
. Voit esimerkiksi määrittää Aseta
, Aseta
tai Aseta
.Työntekijä
ja sen alaluokat.ulottuu
jota seuraa ylärajan tyypin nimi.luokan työntekijät
rajoittaa tyyppejä, joille voidaan välittää Työntekijät
että Työntekijä
tai alaluokka (esim. Kirjanpitäjä
). Määritetään uudet työntekijät
olisi laillista, kun taas uudet työntekijät
olisi laitonta.&
). Tutustu luetteloon 2.Listaus 2:
GenDemo.java
(versio 2)tuo java.math.BigDecimal; tuo java.util.Arrays; abstrakti luokka Työntekijä {yksityinen BigDecimal hourlySalary; yksityinen merkkijono nimi; Työntekijä (jonon nimi, BigDecimal hourlySalary) {tämä.nimi = nimi; this.hourlySalary = hourlySalary; } public BigDecimal getHourlySalary () {return hourlySalary; } public String getName () {palautusnimi; } public String toString () {return name + ":" + hourlySalary.toString (); }} -luokan kirjanpitäjä laajentaa työntekijöiden toteutuksia Vertailukelpoinen {kirjanpitäjä (merkkijonon nimi, BigDecimal hourlySalary) {super (nimi, hourlySalary); } public int CompareTo (Accountant acct) {return getHourlySalary (). CompareTo (acct.getHourlySalary ()); }} luokka SortedEmployees
Työntekijä
luokka tiivistää tuntipalkkaa saavan työntekijän käsitteen. Tämä luokka on alaluokassa Kirjanpitäjä
, joka myös toteuttaa Vertailukelpoinen
osoittamaan sen Kirjanpitäjä
Niitä voidaan verrata niiden luonnollisen järjestyksen mukaan, joka sattuu olemaan tuntipalkka tässä esimerkissä.java.lang.Vertailtavissa
käyttöliittymä ilmoitetaan yleiseksi tyypiksi, jolla on yhden tyyppinen parametri T
. Tämä käyttöliittymä tarjoaa int vertaa (T o)
menetelmä, joka vertaa nykyistä objektia argumenttiin (tyypin T
), palauttamalla negatiivisen kokonaisluvun, nollan tai positiivisen kokonaisluvun, koska tämä objekti on pienempi, yhtä suuri tai suurempi kuin määritetty objekti.LajiteltuTyöntekijät
luokan avulla voit tallentaa Työntekijä
alaluokan esiintymät, jotka toteutetaan Vertailukelpoinen
sisäisessä taulukossa. Tämä taulukko on lajiteltu ( java.util.Arrays
luokan void sort (Object [] a, int fromIndex, int toIndex)
luokan menetelmä) tuntipalkan nousevassa järjestyksessä Työntekijä
alaluokan esiintymä lisätään.javac GenDemo.java
) ja suorita sovellus (java GenDemo
). Ota huomioon seuraava tulos:George Smith: 15.20 Jane Jones: 25.60 John Doe: 35.40
Alemmat rajat ja yleiset tyypin parametrit
Ottaen huomioon jokerimerkit
Listaus 3:
GenDemo.java
(versio 3)tuo java.util.ArrayList; tuoda java.util.Iterator; tuo java.util.List; julkinen luokka GenDemo {public static void main (String [] args) {Lista reittiohjeet = new ArrayList (); reittiohjeet.add ("pohjoinen"); reittiohjeet.add ("etelä"); reittiohjeet.add ("itä"); reittiohjeet.add ("länsi"); printList (ohjeet); Luetteloluokat = new ArrayList (); arvosanat. lisää (uusi kokonaisluku (98)); arvosanat lisää (uusi kokonaisluku (63)); arvosanat. lisää (uusi kokonaisluku (87)); printList (arvosanat); } staattinen void printList (luetteloluettelo) {Iterator iter = list.iterator (); while (iter.hasNext ()) System.out.println (iter.next ()); }}