
Vrste
Java je statički otkucan jezik, što znači da prije upotrebe morate deklarirati varijablu i njen tip.
Na primjer: int myInteger = 42;
Unesite generičke vrste.
Generički tipovi
Definicija: " Generički tip je generička klasa ili sučelje koje se parametrizira u odnosu na tipove."
U osnovi, generički tipovi omogućuju vam pisanje opće, generičke klase (ili metode) koja radi s različitim vrstama, što omogućuje ponovnu upotrebu koda.
Umjesto da odredite obj
da je int
tipa, String
tipa ili bilo kojeg drugog tipa, definirate Box
klasu koja prihvaća parametar tipa <
; T>. Zatim možete n
koristiti T za predstavljanje tog generičkog tipa u bilo kojem dijelu vaše klase.
Sada unesite kovarijanciju i kontravarijanciju.
Kovarijancija i kontravarijancija
Definicija
Varijansa se odnosi na to kako se podtipiranje složenijih tipova odnosi na podtipiranje njihovih komponenata (izvor).
Jednostavna (i krajnje neformalna) definicija kovarijancije i kontravarijance je:
- Kovarijancija: prihvaća podtipove
- Kontravarijansa: prihvatite supertipove
Nizovi
U Javi su nizovi kovarijantni , što ima dvije implikacije.
Prvo, niz vrsta T[]
može sadržavati elemente tipa T
i njegove podtipove.
Number[] nums = new Number[5];nums[0] = new Integer(1); // Oknums[1] = new Double(2.0); // Ok
Drugo, niz vrsta S[]
je podvrsta T[]
if S
je podtip tipa T
.
Integer[] intArr = new Integer[5];Number[] numArr = intArr; // Ok
Međutim, važno je imati na umu da je: (1) numArr
referenca referentnog tipa Number[]
na "stvarni objekt" intArr
"stvarnog tipa" Integer[]
.
Stoga će se sljedeći redak izvrsno kompilirati, ali će stvoriti vrijeme izvođenja ArrayStoreException
(zbog onečišćenja gomile):
numArr[0] = 1.23; // Not ok
Proizvodi runtime iznimku, jer Java tijekom izvođenja zna da je "stvarni objekt" intArr
zapravo niz Integer
.
Generički lijekovi
Kod generičkih tipova Java nikako ne može tijekom izvođenja znati podatke o tipu parametara tipa zbog brisanja tipa. Stoga ne može zaštititi od onečišćenja hrpom tijekom izvođenja.
Kao takvi, generički lijekovi su invarijantni.
ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Not okArrayList anotherIntArrList = intArrList; // Ok
Parametri tipa moraju se točno podudarati kako bi se zaštitili od onečišćenja gomile.
Ali unesite zamjenske znakove.
Zamjenski znakovi, kovarijancija i kontravarijancija
Uz zamjenske znakove moguće je da generički lijekovi podržavaju kovarijanciju i kontravarijanciju.
Ugađajući prethodni primjer, dobivamo ovo, što djeluje!
ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Ok
Znak pitanja "?" odnosi se na zamjenski znak koji predstavlja nepoznati tip. Može biti niže ograničena, što ograničava nepoznati tip da bude određeni tip ili njegov nadtip.
Stoga se u retku 2 ? super Integer
prevodi u "bilo koji tip koji je Integer tip ili njegov supertip".
Možete i gornjom granicom zamjenskog znaka, koji ograničava nepoznati tip da bude određeni tip ili njegov podtip, pomoću ? extends Integer
.
Samo za čitanje i samo za pisanje
Kovarijancija i kontravarijacija daju neke zanimljive ishode. Kovarijantni tipovi su samo za čitanje, dok su kontravarijantni tipovi samo za čitanje.
Zapamtite da kovarijantni tipovi prihvaćaju podtipove, pa ArrayList
er> can contain any object that is either
of a
Number type or its subtype.
In this example, line 9 works, because we can be certain that whatever we get from the ArrayList can be upcasted to a
Number
type (because if it extends Number
, by definition, it is a Number
).
But
nums.add()
doesn’t work, because we cannot be sure of the “actual type” of the object. All we know is that it must be a Number
or its subtypes (e.g. Integer, Double, Long, etc.).
With contravariance, the converse is true.
Line 9 works, because we can be certain that whatever the “actual type” of the object is, it must be
Integer
or its supertype, and thus accept an Integer
object.
But line 10 doesn’t work, because we cannot be sure that we will get an
Integer
. For instance, nums
could be referencing an ArrayList of Objects
.
Applications
Therefore, since covariant types are read-only and contravariant types are write-only (loosely speaking), we can derive the following rule of thumb: “Producer extends, consumer super”.
A producer-like object that produces objects of type
T
can be of type parameter
T>, while a consumer-like object that consumes objects of
type T can be of type para
meter
super T>.