Java Generics - vs.

1. Pregled

U ovom brzom vodiču vidjet ćemo sličnosti i razlike između i u Java Generics.

Međutim, budući da je ovo napredna tema, neophodno je steći osnovno razumijevanje teme prije nego što zaronimo u srž stvari.

2. Pozadina generičkih lijekova

Generički lijekovi uvedeni su u JDK 5 kako bi se eliminirale pogreške tijekom sastavljanja i ojačala sigurnost tipa. Ova dodatna sigurnost za tip eliminira lijevanje u nekim slučajevima korištenja i omogućuje programerima da napišu generičke algoritme, što oboje može dovesti do čitljivijeg koda.

Na primjer, prije JDK 5, morali bismo raditi s elementima popisa pomoću lijevanja. To je, pak, stvorilo određenu klasu runtime pogrešaka:

Popis aList = novi ArrayList (); aList.add (novi cijeli broj (1)); aList.add ("a_string"); for (int i = 0; i <aList.size (); i ++) {Integer x = (Integer) aList.get (i); }

Sad ovaj kôd ima dva problema koja bismo željeli riješiti:

  • Za izlučivanje vrijednosti potrebna nam je eksplicitna uloga popis - tip ovisi o tipu varijable slijeva - Cijeli broj u ovom slučaju
  • Dobit ćemo pogrešku u izvođenju na drugoj iteraciji kada pokušavamo emitirati žica do an Cijeli broj

Uloge za nas ispunjavaju generički lijekovi:

Popis iList = novi ArrayList (); iList.add (1); iList.add ("a_string"); // pogreška vremena kompajliranja za (int i = 0; i <iList.size (); i ++) {int x = iList.get (i); } 

Kompajler će nam reći da to nije moguće dodati žica do a Popis tipa Cijeli broj, što je bolje od saznanja tijekom izvođenja.

Štoviše, nije potrebno izričito lijevanje jer to prevodilac već zna iList drži Cijeli brojs. Uz to, zbog čarolije raspakiranja, nismo ni trebali Cijeli broj tipa, dovoljan je njegov primitivni oblik.

3. Zamjenski znakovi u generičkim lijekovima

Znak pitanja ili zamjenski znak koristi se u generičkim lijekovima za predstavljanje nepoznate vrste. Može imati tri oblika:

  • Neograničeni zamjenski znakovi: Popis predstavlja popis nepoznatog tipa
  • Gornje ograničeni zamjenski znakovi: Popis predstavlja popis Broj ili njegovih podvrsta kao što su Cijeli broj i Dvostruko
  • Donji ograničeni zamjenski znakovi: Popis predstavlja popis Cijeli broj ili njegovih supertipova Broj i Objekt

Sad, otkako Objekt je svojstveni supertip svih vrsta u Javi, bili bismo u iskušenju pomisliti da može predstavljati i nepoznati tip. Drugim riječima, Popis i Popis mogao poslužiti u istu svrhu. Ali nemaju.

Razmotrimo ove dvije metode:

javna statička void printListObject (Lista popisa) {za (Element objekta: popis) {System.out.print (element + ""); }} javna statička praznina printListWildCard (popis popisa) {za (element objekta: popis) {System.out.print (element + ""); }} 

S obzirom na popis Cijeli brojs, recimo:

Popis li = Arrays.asList (1, 2, 3);

printListObject (li) neće se prevesti i dobit ćemo ovu pogrešku:

Metoda printListObject (List) nije primjenjiva za argumente (List)

Dok printListWildCard (li) sastavit će se i izvest će 1 2 3 na konzolu.

4. i - sličnosti

U gornjem primjeru, ako promijenimo potpis metode za printListWildCard do:

javna statička praznina printListWildCard (popis popisa)

Funkcionirao bi na isti način kao i printListWildCard (popis popisa) učinio. To je zbog činjenice da Objekt je supertip svih Java objekata i u osnovi se sve proteže Objekt. Dakle, a Popis od Cijeli brojs se također obrađuje.

Ukratko, to znači da ? i ? proteže se Objekt su u ovom primjeru sinonimi.

Iako bi u većini slučajeva to vrijedilo, ali postoji i nekoliko razlika. Pogledajmo ih u sljedećem odjeljku.

5. i - razlika

Tipovi koji se mogu popraviti su oni čiji se tip ne briše u vrijeme sastavljanja. Drugim riječima, runtime predstavljanje tipa koji se ne može popraviti imat će manje informacija od svog kolege vremena kompajliranja, jer će se neki od njih izbrisati.

Općenito je da se parametrizirani tipovi ne mogu ponovno popraviti. To znači Popis i Karta nisu reifiable. Prevoditelj briše njihov tip i tretira ih kao Popis i Karta odnosno.

Jedina iznimka od ovog pravila su neograničene vrste zamjenskih znakova. To znači Popis i Karta su reifiable.

S druge strane, Popis nije reifiable. Iako je suptilna, ovo je značajna razlika.

Neizmijenjivi tipovi ne mogu se koristiti u određenim situacijama kao što je instanceof operator ili kao elementi niza.

Dakle, ako napišemo:

Navedi someList = novi ArrayList (); boolean instanceTest = someList instanceof List

Ovaj kod kompilira i instanceTest je pravi.

Ali, ako koristimo instanceof operater na Popis:

Navedi anotherList = novi ArrayList (); boolean instanceTest = anotherList instanceof List;

tada se redak 2 ne sastavlja.

Slično tome, u donjem isječku, redak 1 se kompilira, ali redak 2 ne:

Popis [] arrayOfList = novi Popis [1]; Popis [] arrayOfAnotherList = novi popis [1]

6. Zaključak

U ovom kratkom vodiču vidjeli smo sličnosti i razlike u i .

Iako su uglavnom slične, postoje suptilne razlike između njih dvoje u pogledu mogućnosti ponovnog postavljanja ili ne.