Un tipo generico è una classe o un'interfaccia generica parametrizzata su dei tipi. Questo permette al compilatore di imporre la sicurezza dei tipi sulla classe o sull'interfaccia.
Considera questa interfaccia Container non generica:
class Container {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
Poiché accetta e restituisce tipi Object, funziona con qualsiasi tipo non primitivo.
Tuttavia questo ha un costo, perché del codice potrebbe chiamare get aspettandosi degli Integer mentre altro codice chiama set aggiungendo delle String, cosa che produce un'eccezione a runtime.
Una classe generica e un'interfaccia generica hanno il formato seguente:
class ClassName<T1, T2, ..., Tn> { ... }
interface InterfaceName<T1, T2, ..., Tn> { ... }
La sezione dei parametri di tipo, delimitata dalle parentesi angolari (<>) che seguono il nome della classe o dell'interfaccia, specifica i parametri di tipo (detti anche variabili di tipo) T1, T2, ..., e Tn.
Questi possono essere usati all'interno del corpo della classe o dell'interfaccia per ottenere la sicurezza dei tipi generici.
Ecco la versione generica di Container:
class Container<E> {
private E object;
public void set(E object) { this.object = object; }
public E get() { return object; }
}
Quando la creiamo, dobbiamo dichiarare quale tipo contiene e il compilatore imporrà quel vincolo:
// empty <> can infer from context
Container<String> stringContainer = new Container<>();
// compiler knows this is a String, so it is allowed
stringContainer.set("Some string");
// no cast needed, compiler knows it is a String
String result = stringContainer.get();
// this causes a compiler error:
stringContainer.set(42);
In Java, le liste sono la collezione che rappresenta una sequenza ordinata.
A differenza degli array, una List può crescere in dimensione per contenere qualsiasi numero di elementi.
Una delle implementazioni standard è ArrayList, che si basa su un array ridimensionabile.
Un'altra implementazione standard è la classe LinkedList, che si basa su una lista doppiamente concatenata.
Le List possono essere vuote o contenere qualsiasi numero di elementi (duplicati inclusi).
Le List sono un'interfaccia generica tipizzata per indicare quale tipo di oggetti possono contenere.
Ad esempio:
List<String> emptyListOfStrings = List.of();
List<Integer> singleInteger = List.of(1);
List<Boolean> threeBooleans = List.of(true, false, true);
List<Object> listWithMultipleTypes = List.of("hello", 1, true);
Le List hanno vari metodi utili per aggiungere, rimuovere e ottenere elementi, e per verificare la presenza di un elemento:
List<Character> vowels = new ArrayList<>(List.of('a', 'e', 'i', 'o', 'i', 'e', 'a'));
int startingSize = vowels.size(); // 7
vowels.add('u'); // vowels is now ['a', 'e', 'i', 'o', 'i', 'e', 'a', 'u']
char a = vowels.get(0); // 'a'
boolean hadI = vowels.remove('i'); // true and vowels is now ['a', 'e', 'o', 'i', 'e', 'a', 'u']
boolean hasI = vowels.contains('i'); // true (still have one more left)
Karl vuole tenere traccia di un array di linguaggi da imparare sul sito di Exercism. Karl deve poter aggiungere nuovi linguaggi, rimuoverne di vecchi e controllare se certi linguaggi sono nell'array. Sarebbe davvero entusiasmante se Karl volesse imparare Java o Kotlin!
Karl deve sapere se il suo array di linguaggi diventa vuoto, così può andare a cercarne altri da imparare!
Definisci un metodo chiamato isEmpty che restituisce true se non ci sono linguaggi nell'array.
if (languageList.isEmpty()) {
findMoreLanguagesToLearn();
}
Karl non vede l'ora di imparare Kotlin e Python!
Aiuta Karl a iniziare definendo un metodo chiamato addLanguage che prende il linguaggio che vuole imparare e lo aggiunge all'array.
languageList.addLanguage("Kotlin");
languageList.addLanguage("Python");
Karl ha deciso che al momento non vuole imparare Scala.
Aiuta Karl a rimuoverlo dall'array definendo un metodo chiamato removeLanguage che prende il linguaggio che sta rimuovendo e lo elimina dall'array.
languageList.removeLanguage("Scala");
Karl vuole ricordare il primo linguaggio che ha aggiunto all'array (che è ancora nell'array).
Definisci un metodo chiamato firstLanguage che restituisce il primo linguaggio dell'array.
String kotlin = languageList.firstLanguage(); // "Kotlin"
Karl deve sapere quanti linguaggi sta cercando di imparare.
Aiuta Karl a trovare la risposta definendo un metodo chiamato count che restituisce il numero di linguaggi nell'array.
int two = languageList.count(); // 2
Karl sta cercando di ricordare se voleva imparare Python o Ruby.
Definisci un metodo chiamato containsLanguage che prende il linguaggio su cui sta chiedendo, così Karl può scoprirlo!
boolean learningPython = languageList.containsLanguage("Python"); // true
boolean learningRuby = languageList.containsLanguage("Ruby"); // false
Se Karl vuole imparare Java o Kotlin, è davvero entusiasmante!
Definisci un metodo chiamato isExciting che restituisce true se Karl vuole imparare Java o Kotlin.
javaLanguageList.isExciting() // true
neitherKotlinNorJavaLanguageList.isExciting() // false
Iscriviti a Exercism per imparare e padroneggiare Java con 26 concetti158 esercizi e il mentoring di persone reali, tutto gratis.