Non so perché questa compilazione. D'altra parte, posso spiegare come è possibile sfruttare appieno i controlli in fase di compilazione.
Quindi, newList()
è un metodo generico, ha un parametro di tipo. Se si specifica questo parametro, il compilatore verificherà che per voi:
fallisce la compilazione:
String s = Main.<String>newList(); // this doesn't compile anymore
System.out.println(s);
passa la fase di compilazione:
List<Integer> l = Main.<ArrayList<Integer>>newList(); // this compiles and works well
System.out.println(l);
Specificando thetype parametro
T I parametri di tipo forniscono solo il controllo in fase di compilazione. Questo è in base alla progettazione, java utilizza type erasure per i tipi generici. Per far funzionare il compilatore per te, devi specificare quei tipi nel codice.
parametro Type in grado di creazione
Il caso più comune è quello di specificare i modelli di un'istanza di oggetto. Cioè per gli elenchi:
List<String> list = new ArrayList<>();
Qui possiamo vedere che List<String>
specifica il tipo per le voci di elenco. D'altra parte, nuovo ArrayList<>()
no. Utilizza invece lo diamond operator. Cioè il compilatore java infers il tipo basato sulla dichiarazione.
parametro di tipo implicito alla chiamata di metodo
Quando si richiama un metodo statico, allora è necessario specificare il tipo in un altro modo. A volte è possibile specificare come parametro:
public static <T extends Number> T max(T n1, T n2) {
if (n1.doubleValue() < n2.doubleValue()) {
return n2;
}
return n1;
}
La si può usare in questo modo:
int max = max(3, 4); // implicit param type: Integer
O come questa:
double max2 = max(3.0, 4.0); // implicit param type: Double
espliciti parametri di tipo a chiamata di metodo:
Per esempio, questo è il modo in cui può creare un tipo-safe elenco vuoto:
List<Integer> noIntegers = Collections.<Integer>emptyList();
Il tipo di parametro <Integer>
viene passato al metodo emptyList()
. L'unico vincolo è che devi specificare anche la classe. Cioè Non si può fare questo: tipo
import static java.util.Collections.emptyList;
...
List<Integer> noIntegers = <Integer>emptyList(); // this won't compile
Runtime gettone
Se nessuno di questi trucchi può aiutare, allora è possibile specificare un runtime type token. Cioè fornisci una classe come parametro. Un esempio comune è l'EnumMap:
private static enum Letters {A, B, C}; // dummy enum
...
public static void main(String[] args) {
Map<Letters, Integer> map = new EnumMap<>(Letters.class);
}
correlati http://stackoverflow.com/questions/36402646/generic-return-type-upper-bound-interface-vs-class-surprisingly-valid-code – Tunaki
Il motivo dell'aggiornamento che fa la differenza è che il primo la versione può funzionare se esiste un tipo che soddisfa i vincoli (T estende la lista e T estende String) [cioè è una quantificazione esistenziale], mentre la seconda versione può funzionare solo se tutti i possibili tipi T che corrispondono alla dichiarazione nella classe estendono anche String [vale a dire è una quantificazione universale]. –