1. Toate clasele moștenescObject
Toate clasele din Java moștenesc implicit Object
clasa.
Vom analiza ce este moștenirea și cum funcționează ea în Java în misiunea Java Core. Pentru moment, vom lua în considerare un fapt simplu care decurge din aceasta:
Un obiect din orice clasă poate fi atribuit unei Object
variabile. Exemplu:
Cod | Notă |
---|---|
|
Variabila o stochează o referință la un Scanner obiect |
|
Variabila o stochează o referință la un String obiect |
|
Variabila o stochează o referință la un Integer obiect |
|
Variabila o stochează o referință la un String obiect |
Aici se termină vestea bună. Compilatorul nu ține evidența tipului original de obiect salvat într-o Object
variabilă, așa că nu veți putea apela metode pe obiectul salvat, altele decât metodele clasei Object
.
Dacă trebuie să apelați metodele asociate cu tipul original al obiectului, atunci trebuie să salvați mai întâi o referință la acesta într-o variabilă de tipul corect, apoi să apelați metodele pe acea variabilă:
Cod | Notă |
---|---|
|
Programul nu se va compila. Clasa Object nu are nicio nextInt() metodă. |
|
Acest lucru va funcționa. Aici salvăm o referință la un Scanner obiect într-o Scanner variabilă utilizând un operator typecast . |
Nu puteți să atribuiți o Object
variabilă unei variabile Scanner, chiar dacă Object
variabila stochează o referință la un Scanner
obiect. Dar puteți face acest lucru dacă utilizați operatorul typecast , despre care știți deja. Acesta este aspectul său general:
Type name1 = (Type) name2;
Unde name1
este numele unei Type
variabile și name2
este numele unei Object
variabile care stochează o referință la un Type
obiect.
Tipare
Dacă tipul variabilei și tipul obiectului nu se potrivesc, atunci ClassCastException
va fi aruncat a. Exemplu:
Cod | Notă |
---|---|
|
Va apărea o eroare în timpul execuției: aici va fi aruncat a ClassCastException |
Există o modalitate de a evita această eroare în Java: facem acest lucru verificând tipul obiectului stocat într-o variabilă :
name instanceof Type
Operatorul instanceof
verifică dacă name
variabila este un Type
obiect.
De exemplu, să găsim un șir într-o matrice de diverse obiecte:
Cod | Notă |
---|---|
|
Autoboxing va converti aceste valori într-un Integer , String , și Double , respectiv. Buclă peste matricea de obiecte Dacă obiectul este un String Salvare într-o String variabilă Afișează variabila pe ecran. |
2. De ce au apărut genericele — colecții
Să revenim la colecții.
De îndată ce dezvoltatorii Java au creat ArrayList
clasa, au vrut să o facă universală, astfel încât să poată stoca orice tip de obiect. Deci au folosit o serie de Object
s pentru a stoca elementele.
Punctul forte al acestei abordări este că puteți adăuga un obiect de orice tip la colecție.
Desigur, există mai multe puncte slabe.
Dezavantaj 1.
A fost întotdeauna necesar să scrieți un operator de conversie de tip atunci când recuperați elemente dintr-o colecție:
Cod | Notă |
---|---|
|
Creați o colecție pentru a stoca referințe la Object obiecte Umpleți colecția cu numere 10 , 20 , ... 100 ; Însumați elementele colecției Typecasting este necesar |
Dezavantaj 2.
Nu exista nicio garanție că o colecție conține un anumit tip de element
Cod | Notă |
---|---|
|
Creați o colecție pentru a stoca referințe la Object obiecte Umplem colecția cu numere reprezentate ca Double obiecte: 0.0 , 2.5 , 5.0 , ... Însumăm elementele colecției Va apărea o eroare: a Double nu poate fi turnat într-unInteger |
Datele pot fi introduse în colecție oriunde:
- într-o altă metodă
- într-un alt program
- dintr-un dosar
- prin rețea
Dezavantaj 3.
Datele din colecție pot fi modificate accidental.
Puteți trece o colecție plină cu datele dvs. către o anumită metodă. Această metodă, scrisă de un alt programator, adaugă datele sale la colecția ta.
Numele colecției nu indică clar ce tipuri de date pot fi stocate în ea. Și chiar dacă dați variabilei dvs. un nume clar, o referință la aceasta poate fi transmisă la o duzină de metode, iar acele metode cu siguranță nu vor ști nimic despre numele original al variabilei.
3. Generice
În Java, toate aceste probleme sunt eliminate de acest lucru grozav numit generice.
În Java, genericele înseamnă capacitatea de a adăuga parametri de tip la tipuri. Rezultatul este un tip compozit complex. Vederea generală a unui astfel de tip compozit este următoarea:
ClassName<TypeParameter>
Aceasta este o clasă generică. Și poate fi folosit oriunde folosiți în mod normal cursurile.
Cod | Descriere |
---|---|
|
Crearea variabilelor |
|
Crearea obiectelor |
|
Crearea de tablouri |
Integer
Într-o astfel de colecție pot fi stocate doar variabile:
Cod | Descriere |
---|---|
|
ArrayList colectare cu Integer elemente Acest lucru este permis Și va funcționa și asta
Autoboxing
Dar acest lucru nu este permis: eroare de compilare |
Veți învăța cum să vă creați propriile clase cu parametri de tip în misiunea Java Collections. Deocamdată, ne vom uita la cum să le folosim și cum funcționează.
4. Cum funcționează genericele
De fapt, genericele sunt teribil de primitive.
Compilatorul înlocuiește pur și simplu tipurile generice cu tipuri obișnuite. Dar atunci când sunt utilizate metode de tip generic, compilatorul adaugă un operator de tipar pentru a arunca parametrii la parametrii de tip:
Cod | Ce face compilatorul |
---|---|
|
|
|
|
|
|
|
|
Să presupunem că avem o metodă care însumează numerele dintr-o colecție de numere întregi:
Cod | Ce face compilatorul |
---|---|
|
|
Cu alte cuvinte, genericele sunt un fel de zahăr sintactic, la fel ca autoboxing-ul, dar puțin mai mult. Cu autoboxing, compilatorul adaugă metode pentru conversia an int
în an Integer
și invers, iar pentru generice adaugă operatori typecast.
După ce compilatorul compilează clasele dvs. generice cu parametrii de tip, acestea sunt pur și simplu convertite în clase obișnuite și operatori typecast. Informațiile despre argumentele tip transmise variabilelor de tipuri generice se pierd. Acest efect se mai numește și ștergere de tip .
Uneori, programatorii care scriu clase generice (clase cu parametri de tip) chiar au nevoie de informații despre tipurile transmise ca argumente. În misiunea Java Collections, veți învăța cum să faceți față acestui lucru și ce implică.
5. Câteva fapte despre generice
Iată câteva fapte mai interesante despre medicamente generice.
Clasele pot avea mai mulți parametri de tip. Arata cam asa:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
De fapt, acest lucru nu este chiar surprinzător. Oriunde compilatorul poate adăuga un operator pentru a turna la un singur tip, poate adăuga mai mulți operatori de tipare.
Exemple:
Cod | Notă |
---|---|
|
Primul put parametru al metodei este an Integer , iar al doilea este aString |
Tipurile generice pot fi folosite și ca parametri . Arata cam asa:
ClassName<TypeParameter<TypeParameterParameter>>
Să presupunem că vrem să creăm o listă care să stocheze liste de șiruri. În acest caz, vom obține ceva de genul acesta:
// List of greetings
ArrayList<String> listHello = new ArrayList<String>();
listHello.add ("Hello");
listHello.add ("Hi");
// List of goodbyes
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Bye");
listBye.add ("Goodbye");
// List of lists
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
Tipurile generice (tipuri cu parametri de tip) pot fi, de asemenea, utilizate ca tipuri de matrice. Arata cam asa:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Nu se întâmplă nimic magic aici: parantezele unghiulare indică doar numele tipului:
Cod | Omologul negeneric |
---|---|
|
|
|
|
|
|
GO TO FULL VERSION