2011-01-23 4 views
10

In Java, perché non è possibile che un array sia vincolato da una variabile di tipo, ma può essere associato a un carattere jolly?In Java, perché un array non può essere associato a una variabile di tipo, ma può essere associato a un carattere jolly?

Si possono avere:

List< ? extends Integer[] > l; 

, ma non si può avere:

class MyClass< T extends Integer[] > { } // ERROR! 

Perché?

+0

È strano. Il JLS afferma chiaramente che è possibile utilizzare solo le classi o le interfacce in variabili di tipo, ma non fornisce alcuna spiegazione di sorta. – biziclop

+0

solo per fare come-confronti: "Elenco k1;" è permesso, ma "List k2;" non è. Ma non ho trovato nulla tranne null da aggiungere alla lista! Eclipse dice che k1.get (0) restituisce il tipo Integer [], ma non è stato possibile aggiungerne uno. –

risposta

7

Considerate questo codice Java:

package test; 

public class Genric<E> 
{ 
    public Genric(E c){ 
     System.out.println(c.getClass().getName()); 
    } 
    public static void main(String[] args) { 
     new Genric<Integer[]>(new Integer[]{1,2}); 
    } 
} 

Per il primo caso:

List< ? extends Integer[] > l; 

Quando fai qualcosa di simile List< ? extends Integer[] > l; poi il compilatore Java vede come un List< ? extends Object> l; e lo traduce di conseguenza . Quindi questo è il motivo per cui non si ottiene alcun errore.

Il byte-codice generato è il seguente:

. 
    . 
    . 
    20: aastore 
    21: invokespecial #52; //Method "<init>":(Ljava/lang/Object;)V 
    24: return 
    . 
    . 

partenza il numero di riga . Sebbene, ho passato una serie di java.lang.Integer; internamente è tradotto in java.lang.Object.

Per il secondo caso:

class MyClass< T extends Integer[] > { } // ERROR! 

Come da Java specifica del linguaggio:

TypeParameter: 
TypeVariable TypeBoundopt 

TypeBound: 
extends ClassOrInterfaceType AdditionalBoundListopt 
. 
. 

Come si può vedere il il limite è costituito esclusivamente di classe o un'interfaccia (nemmeno tipi primitivi). Quindi quando fai qualcosa di simile a questo class MyClass< T extends Integer[] > { } allora Integer[] non si qualifica come una classe o interfaccia.

Come per la mia comprensione di Java Spec, questo è stato fatto per risolvere tutti gli scenari come

  1. class MyClass< T extends Integer[] >
  2. class MyClass< T extends Integer[][] >
  3. ..
  4. class MyClass< T extends Integer[][]...[] >

Poiché tutti loro possono essere rappresentati come java.lang.Object e quando passati come parametro, come nell'esempio

public Genric(E c){ 
      System.out.println(c.getClass().getName()); 
     } 

come 'c' ricorda il suo vero tipo.

Spero che questo possa essere d'aiuto.

+0

+1 per scavare nel proprio bytecode, sebbene questo sia più simile a una spiegazione di "hows" piuttosto che "perché". Non è la sostituzione del parametro type con 'Object' semplicemente a causa della cancellazione di tipo , e applicato sempre? Cioè List 'diventerebbe anche un' List 'nel bytecode non è vero? La sicurezza del tipo generico viene controllata solo dal compilatore prima che si verifichi la cancellazione del tipo. –

0

Si può fare qualcosa di simile:

public class MyClass<K> { 
    K array; 
    public MyClass(K k) { 
     array = k; 
    } 

Oppure si potrebbe fare qualcosa di simile:

class MyClass< T extends Integer > { 
    ...make your variable MyClass[]... 
} 

Spero che questo aiuti e io non sono troppo lontano quello che stavi chiedendo.

+0

Credo che lui chieda "WHY" non "HOW TO ..." :( – Xorty

+0

Infatti. Non sto cercando di usare un array come limite per T. Volevo solo sapere perché questa restrizione è imposta –

+0

incomprensione, se mi dici come cancellare questo post me ne sbarazzerò dato che è irrilevante – 4everAStudent

3

Sto cercando di pensare a ragioni specifiche questo dovrebbe essere vietata, ma l'unico che mi viene in mente è che è un costrutto completamente inutile, perché:

class Foo<T extends Integer[]> { 
    T bar(); 
} 

è equivalente a

class Foo<T extends Integer> { 
    T[] bar(); 
} 

Ovviamente non si può dire lo stesso del caso con caratteri jolly, quindi è consentito lì.