2015-10-16 12 views
7

Ecco il codice:Generics cancellazione del tipo in Java

public class Main { 
    public static void main(String[] args) { 
     Gen<Integer> g = new Gen<Integer>(5); 

     System.out.println(g.getClass()); 
     System.out.println(g.ob.getClass()); 
    } 
} 

class Gen<T> { 
    T ob; 

    public Gen(T x) { 
     ob = x; 
    } 
} 

Ed ecco l'output

class Gen    // This I understand 
class java.lang.Integer // But if type erasure is happening, shouldn't this be java.lang.Object? 

ho capito che il parametro Type T viene cancellato in fase di esecuzione, ma allora perché è il parametro tipo di ob sopravvivendo al runtime?

+3

Avrai bisogno di iniziare a distinguere tra variabili, riferimenti e oggetti, –

+2

Se 'Car c = new Mercedes();' cosa pensi dovrebbe essere il risultato di 'c.getClass()' e perché? – Pshemo

+0

grazie a tutti per aver risposto ora lo ricevo – Ramanlfc

risposta

0

Poiché la mia prima esposizione ai generici è stata con C#, è stato necessario tempo per capire cos'è il tipo di cancellazione in java.

Ma dopo aver compreso meglio i java generics, ho capito che nella mia domanda sto mescolando 2 argomenti separati: Generics and Reflection.

La questione principale era, perché ha fatto la seconda chiamata qui

System.out.println(g.getClass()); 
System.out.println(g.ob.getClass()); 

restituito java.lang.Integer invece di java.lang.Object.

Guardando la documentazione per getClass(), la risposta diventa ovvia

Restituisce il runtime classe di questo oggetto.

quindi, getClass() non restituisce il tipo di riferimento ma l'oggetto reale a cui fa riferimento il riferimento.

Ad es:

Object o = "abc"; 
System.out.println(o.getClass()); 

L'uscita non sarebbe il tipo di riferimento java.lang.Object ma piuttosto il tipo dell'oggetto java.lang.Stringeffettivo.

2

Type erasure sta accadendo. I generici sono un sistema di controllo del tipo a tempo compilato. Al momento dell'esecuzione si ottiene ancora la classe (si tratta di informazioni sul tipo di esecuzione). La documentazione sulla cancellazione del tipo collegato dice (in parte)

I generici sono stati introdotti nel linguaggio Java per fornire controlli di tipo più severi in fase di compilazione e per supportare la programmazione generica. Per implementare i generici, il compilatore Java applica la cancellazione del tipo a:

Sostituisci tutti i parametri di tipo in tipi generici con i relativi limiti o Oggetto se i parametri di tipo sono illimitati. Il codice prodotto, quindi, contiene solo classi, interfacce e metodi ordinari.

L'istanza ha un tipo, è Object. Ma un riferimento Object può fare riferimento a qualsiasi sottoclasse (che è ogni classe) in Java. Ottieni il tipo a cui si riferisce.

+0

Questo non risponde alla domanda dell'OP sul motivo per cui il tipo di runtime dell'oggetto contenuto non viene "cancellato". – Random832

+0

Ma è (al bytecode), è confuso rtti con informazioni sulla compilazione del tempo. –

4

No!

Considerate questo:

Object x = new Integer(1); 
System.out.println(x.toString()); 

Si otterrà 1.

Ma non dovrei ottenere Object.toString()?

No. Sebbene x è un riferimento di tipo Object, il referente reale è un Integer, quindi in fase di esecuzione, l'attuazione di IntegertoString viene chiamato.

È lo stesso per getClass.

2

Indipendentemente dal tipo di variabile, il valore di ritorno di getClass() dipende dal contenuto della variabile . Quindi, dal momento che in pratica hai una variabile Object ob che contiene un (il tuo int è stato convertito nel momento in cui lo hai fornito come parametro del costruttore), l'output di ob.getClass() è class java.lang.Integer.

Inoltre, sulla tua domanda sul perché getClass() ricorda l'argomento tipo: non lo è. Tutto ciò che fa è determinare la classe del contenuto. Per esempio:

class Foo { 
    public Foo() {} 
} 

class Bar extends Foo { 
    public Bar() {} 
} 

class Baz<T> { 
    public T object; 

    public Baz(T object) { this.object = object; } 
} 

Se ora si esegue il seguente frammento ...

public static void main(String... args) { 
    Baz<Foo> obj = new Baz(new Bar()); 
    System.out.println(obj.object.getClass()); 
} 

si noterà che l'uscita non è class Foo, è class Bar.

2

Perché quando compilato, la classe Gen ha un oggetto Object; I generici scompaiono dal prodotto finale. Le parentesi angolari svolgono un ruolo solo in fase di compilazione, durante il controllo del tipo statico. È qualcosa che il compilatore può fare per darti una maggiore tranquillità, per assicurarti che stai utilizzando correttamente collezioni e altri tipi di parametri.

l'oggetto assegnato a ob in runtime è un'istanza della classe Integer e ob.getClass() serve allo scopo di trovare la classe effettiva dell'oggetto a cui fa riferimento il puntatore -> quindi vedrete java. lang.Intero stampato.

Ricorda, ciò che viene fuori è effettivamente classe Gen {Object ob; ...}

+0

Questo non chiarisce perché 'getClass()' restituisce 'Intero'. –

+0

l'oggetto reale assegnato a ob in runtime è un'istanza della classe Integer. E questo è come lo scopriresti ... –

+0

Dovrebbe essere nella risposta, quindi –