1. Tutte le classi ereditanoObject
Tutte le classi in Java ereditano implicitamente la Objectclasse.
Analizzeremo cos'è l'ereditarietà e come funziona in Java nella ricerca Java Core. Per ora, considereremo un semplice fatto che ne consegue:
Un oggetto di qualsiasi classe può essere assegnato a una Objectvariabile. Esempio:
| Codice | Nota |
|---|---|
|
La ovariabile memorizza un riferimento a un Scanneroggetto |
|
La ovariabile memorizza un riferimento a un Stringoggetto |
|
La ovariabile memorizza un riferimento a un Integeroggetto |
|
La ovariabile memorizza un riferimento a un Stringoggetto |
È qui che finisce la buona notizia. Il compilatore non tiene traccia del tipo originale di oggetto salvato in una Objectvariabile, quindi non sarai in grado di chiamare metodi sull'oggetto salvato diversi dai metodi della Objectclasse.
Se devi chiamare i metodi associati al tipo originale dell'oggetto, devi prima salvare un riferimento ad esso in una variabile del tipo corretto, quindi chiamare i metodi su quella variabile:
| Codice | Nota |
|---|---|
|
Il programma non verrà compilato. La Objectclasse non ha nextInt()metodo. |
|
Questo funzionerà. Qui salviamo un riferimento a un Scanneroggetto in una Scannervariabile usando un operatore typecast . |
Non puoi semplicemente andare e assegnare una Objectvariabile a una variabile Scanner, anche se la Objectvariabile memorizza un riferimento a un Scanneroggetto. Ma puoi farlo se usi l' operatore typecast , che già conosci. Questo è il suo aspetto generale:
Type name1 = (Type) name2;
Dove name1è il nome di una Typevariabile ed name2è il nome di una Objectvariabile che memorizza un riferimento a un Typeoggetto.
Tipografia
Se il tipo di variabile e il tipo di oggetto non corrispondono, ClassCastExceptionverrà lanciato a. Esempio:
| Codice | Nota |
|---|---|
|
Si verificherà un errore in fase di esecuzione: a ClassCastExceptionverrà lanciato qui |
C'è un modo per evitare questo errore in Java: lo facciamo controllando il tipo dell'oggetto memorizzato in una variabile :
name instanceof Type
L' instanceofoperatore controlla se la namevariabile è un Typeoggetto.
Ad esempio, troviamo una stringa in un array di oggetti diversi:
| Codice | Nota |
|---|---|
|
Autoboxing convertirà questi valori rispettivamente in Integer, Stringe Double. Passa sopra l'array di oggetti Se l'oggetto è un StringSalvalo in una Stringvariabile Visualizza la variabile sullo schermo. |
2. Perché sono apparsi i generici: le raccolte
Torniamo alle collezioni.
Non appena gli sviluppatori Java hanno creato la ArrayListclasse, hanno voluto renderla universale, in modo che potesse memorizzare qualsiasi tipo di oggetto. Quindi hanno usato un array di Objects per memorizzare gli elementi.
Il punto di forza di questo approccio è che puoi aggiungere un oggetto di qualsiasi tipo alla collezione.
Naturalmente, ci sono diversi punti deboli.
Svantaggio 1.
Era sempre necessario scrivere un operatore di conversione del tipo durante il recupero di elementi da una raccolta:
| Codice | Nota |
|---|---|
|
Crea una raccolta per memorizzare i riferimenti agli Objectoggetti Riempi la raccolta con i numeri 10, 20, ... 100; Somma gli elementi della collezione Il typecasting è necessario |
Svantaggio 2.
Non c'era alcuna garanzia che una raccolta contenesse un tipo specifico di elemento
| Codice | Nota |
|---|---|
|
Creare una collezione per memorizzare i riferimenti agli Objectoggetti Riempiamo la collezione con i numeri rappresentati come Doubleoggetti: 0.0, 2.5, 5.0, ... Somma gli elementi della collezione Ci sarà un errore: a Doublecannot be cast to anInteger |
I dati possono essere inseriti nella raccolta ovunque:
- in un altro metodo
- in un altro programma
- da un file
- sulla rete
Svantaggio 3.
I dati nella raccolta possono essere modificati accidentalmente.
Puoi passare una raccolta piena dei tuoi dati a un metodo. Quel metodo, scritto da un programmatore diverso, aggiunge i suoi dati alla tua raccolta.
Il nome della raccolta non indica chiaramente quali tipi di dati possono essere archiviati in essa. E anche se dai alla tua variabile un nome chiaro, un riferimento ad essa può essere passato a una dozzina di metodi, e quei metodi sicuramente non sapranno nulla del nome originale della variabile.
3. Generici

In Java, tutti questi problemi vengono eliminati da questa cosa interessante chiamata generici.
In Java, generici significa la possibilità di aggiungere parametri di tipo ai tipi. Il risultato è un tipo composito complesso. La visione generale di un tale tipo composito è questa:
ClassName<TypeParameter>
Questa è una classe generica. E può essere utilizzato ovunque si utilizzino normalmente le classi.
| Codice | Descrizione |
|---|---|
|
Creazione di variabili |
|
Creare oggetti |
|
Creazione di array |
Solo Integerle variabili possono essere memorizzate in una tale raccolta:
| Codice | Descrizione |
|---|---|
|
ArrayListraccolta con Integerelementi Questo è consentito E anche questo funzionerà
Autoboxing
Ma questo non è consentito: errore di compilazione |
Imparerai come creare le tue classi con parametri di tipo nella quest Java Collections. Per ora, vedremo come usarli e come funzionano.
4. Come funzionano i generici
In realtà, i generici sono terribilmente primitivi.
Il compilatore sostituisce semplicemente i tipi generici con tipi ordinari. Ma quando vengono utilizzati metodi di un tipo generico, il compilatore aggiunge un operatore typecast per trasmettere i parametri ai parametri di tipo:
| Codice | Cosa fa il compilatore |
|---|---|
|
|
|
|
|
|
|
|
Supponiamo di avere un metodo che somma i numeri in una raccolta di numeri interi:
| Codice | Cosa fa il compilatore |
|---|---|
|
|
In altre parole, i generici sono una specie di zucchero sintattico, proprio come l'autoboxing, ma un po' di più. Con l'autoboxing, il compilatore aggiunge metodi per convertire an intin an Integere viceversa, e per i generici aggiunge operatori typecast.
Dopo che il compilatore ha compilato le classi generiche con parametri di tipo, vengono semplicemente convertite in classi ordinarie e operatori di typecast. Le informazioni sugli argomenti di tipo passati alle variabili di tipi generici vengono perse. Questo effetto è anche chiamato cancellazione del tipo .
A volte i programmatori che scrivono classi generiche (classi con parametri di tipo) hanno davvero bisogno delle informazioni sui tipi passati come argomenti. Nella ricerca Java Collections, imparerai come affrontare questo problema e cosa comporta.
5. Alcuni fatti sui generici
Ecco alcuni fatti più interessanti sui generici.
Le classi possono avere diversi parametri di tipo. Assomiglia a questo:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
In realtà, questo non è davvero sorprendente. Ovunque il compilatore possa aggiungere un operatore per eseguire il cast a un tipo, può aggiungere più operatori di typecast.
Esempi:
| Codice | Nota |
|---|---|
|
Il putprimo parametro del metodo è an Integere il secondo è aString |
I tipi generici possono essere utilizzati anche come parametri . Assomiglia a questo:
ClassName<TypeParameter<TypeParameterParameter>>
Supponiamo di voler creare un elenco che memorizzerà elenchi di stringhe. In questo caso, otterremo qualcosa del genere:
// 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);
I tipi generici (tipi con parametri di tipo) possono essere utilizzati anche come tipi di matrice. Assomiglia a questo:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Non sta accadendo nulla di magico qui: le parentesi angolari indicano solo il nome del tipo:
| Codice | Controparte non generica |
|---|---|
|
|
|
|
|
|
GO TO FULL VERSION