Ho notato qualcosa mentre stavo scherzando con i generici. Nell'esempio che segue, doStuff1
compila ma doStuff2
non lo fa:Java: getClass() del tipo limitato
public <T extends Foo> void doStuff1(T value) {
Class<? extends Foo> theClass = value.getClass();
}
public <T extends Foo> void doStuff2(T value) {
Class<? extends T> theClass = value.getClass();
}
Così, ho guardato la documentazione per Object.getClass()
e abbiamo trovato questo:
Il tipo di risultato effettivo è di classe <? estende | X | > dove | X | è la cancellazione del tipo statico dell'espressione su cui viene chiamato getClass.
Questo mi ha reso un po 'curioso. Perché lo getClass()
è progettato in questo modo? Riesco a capire i tipi di conversione nelle loro classi raw, se applicabili, ma non vedo ragioni ovvie perché debbano necessariamente farlo uccidere anche T
. Esiste una ragione specifica per cui si sbarazza anche di questo, o è solo un approccio generale "liberiamoci di tutto solo perché è più facile, chi avrebbe mai bisogno comunque"?
Capire questo mi farà male alla testa; Odio calcolare i limiti di tipo generico anche quando non è così tardi. Suggerisco di partire da [il JLS per 'Object'] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.3.2) e guardare la ricerca regole; questo è probabilmente un artefatto di come la JVM fa la sua magia sorta-statica per riflettere sulla classe di runtime dell'oggetto. – chrylis