Domanda

Si consideri il seguente:

public Class<List<String>> getObjectType() {
    // what can I return here?
}

Che classe letterale dell'espressione posso tornare da questo metodo in grado di soddisfare i farmaci generici e compilare? List.class non verrà compilato, e neppure List.<String>class.

Se vi state chiedendo "perché", sto scrivendo un'implementazione di FactoryBean<List<String>> di primavera, che mi obbliga a implementare Class<List<String>> getObjectType(). Tuttavia, questo è non una domanda di primavera.

modifica:. le mie grida lamentose sono state ascoltate dai poteri che essere a SpringSource, e così primavera 3.0.1 avrà il tipo di ritorno di getObjectType() cambiato in Class<?>, che evita accuratamente il problema

È stato utile?

Soluzione

Si può sempre lanciare a che cosa avete bisogno, come questo

return (Class<List<String>>) new ArrayList<String>().getClass();

o

return (Class<List<String>>) Collections.<String>emptyList().getClass();

Ma suppongo che non è quello che cercate. Funziona bene, con un avvertimento, ma non è esattamente "bello".

Ho appena trovato questo

  

Perché non c'è nessuna classe letterale per i tipi parametrici jolly?

     

Perché un tipo parametrico jolly non ha esatta rappresentazione tipo di runtime.

Quindi fusione potrebbe essere l'unico modo per andare.

Altri suggerimenti

Non si dovrebbe mai usare il Class<List<String>> costrutto. E 'assurdo, e dovrebbe produrre un avvertimento in Java (ma non lo fa). istanze di classe rappresentano sempre tipi prime, in modo da poter avere Class<List>; questo è tutto. Se volete qualcosa di rappresentare un tipo generico reificata come List<String>, è necessario un "tipo di token super" come Guice utilizza:

http: //google-guice.googlecode. com / git / javadoc / com / google / Inject / TypeLiteral.html

L'esistenza di un Class<List<String>> è intrinsecamente pericoloso. ecco perché:

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}

questo link su springframework.org che dà una certa comprensione.

per es.

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();

È possibile implementare tale metodo come questo:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}

Check out questa discussione sul forum di SUN:

http://forums.sun.com/thread.jspa?threadID=5253007

E il post sul blog di riferimento che descrive un lavoro in giro usando "tipo token Super":

http://gafter.blogspot.com/2006/12 /super-type-tokens.html

Non sono sicuro se questo è possibile a tutti, dal momento che ogni classe letterale sarà compilato a Class.forName(...) e poiché questo avviene in fase di esecuzione non vi sono informazioni generiche sinistra.

Non sono sicuro, ma alla seguente domanda ho chiesto potrei essere rilevanti per te ...

java parametri generici di tipo e operazioni su quei tipi

Che dire di questo:

public class TestMain {
    public static void main(String[] args) throws Exception {
        Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
        System.out.println("type = " + type);
    }

    public List<Integer> dummy() {return null;}
}

Questo stampa:

type = java.util.List<java.lang.Integer>

Il seguente approccio è problematico:

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }

es. se si desidera verificare se un oggetto dire di tipo

org.eclipse.emf.common.util.BasicEList<String> 

è di tipo

List<String> 

in base al risultato del suddetto approccio getModelType (), ad esempio:

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}

il risultato sarà falso mentre dovrebbe essere vero, perché entrambi gli oggetti implementare la lista di interfaccia (dal getModelType () restituisce un oggetto di classe di tipo List e non ArrayList).

Ecco un approccio che ha funzionato per me (un po 'ingombrante ma porta a correggere risultati dell'esempio precedente, potrebbe essere spostato in un inizializzatore statico):

public Class<List<String>> getModelType() {
    Class<?> arrayListClass = new ArrayList<String>().getClass();
    Class<?>[] interfaces = arrayListClass.getInterfaces();
    int index = 0;
    for (int i = 0; i < interfaces.length; i++) {
        if (interfaces[i].equals(List.class)) {
            index = i;
            break;
        }
    }
    return (Class<List<String>>) interfaces[index];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top