Question

Prendre les éléments suivants:

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

Quelle est l'expression littérale classe puis-je revenir de cette méthode qui satisfera les génériques et la compilation? List.class ne compile pas, et ne sera List.<String>class.

Si vous vous demandez « pourquoi », j'écris une mise en œuvre du FactoryBean<List<String>> de printemps, ce qui me oblige à mettre en œuvre Class<List<String>> getObjectType(). Cependant, cela est pas une question de printemps.

modifier. Mes cris plaintifs ont été entendues par les pouvoirs à être SpringSource, et ainsi de printemps 3.0.1 aura le type de getObjectType() de retour a changé à Class<?>, ce qui évite soigneusement le problème

Était-ce utile?

La solution

Vous pouvez toujours jeter à ce que vous avez besoin, comme ceci

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

ou

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

Mais je suppose que ce n'est pas ce que vous recherchez. Eh bien, il fonctionne, avec un avertissement, mais il est pas tout à fait « beau ».

Je viens de trouver ce

  

Pourquoi est-il pas de classe littérale pour les types génériques paramétrés?

     

Parce que un type paramétrées générique n'a pas de représentation de type d'exécution exacte.

coulée pourrait être la seule façon d'aller.

Autres conseils

Vous ne devez jamais utiliser la Class<List<String>> de construction. Il est absurde et devrait produire un avertissement en Java (mais ne fonctionne pas). Les instances de classes représentent toujours des types premières, afin que vous puissiez avoir Class<List>; c'est ça. Si vous voulez quelque chose pour représenter un type générique réifié comme List<String>, vous avez besoin d'un « jeton de type super » comme Guice utilise:

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

L'existence d'un Class<List<String>> est intrinsèquement dangereux. voici pourquoi:

// 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);
}

ce lien sur springframework.org qui donne un aperçu.

par exemple.

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

Vous pouvez implémenter cette méthode comme ceci:

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

Découvrez cette discussion sur les forums SUN:

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

Et le billet de blog référencé qui décrit un travail autour en utilisant des « super jetons de type »:

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

Je ne sais pas si cela est possible du tout, puisque sera compilé une classe littérale Class.forName(...) et que cela se produit lors de l'exécution il n'y a pas d'information générique gauche.

Je ne suis pas sûr, mais la question suivante j'ai demandé peut-être un intérêt pour vous ...

paramètres java de type génériques et les opérations sur ces types

Qu'en est-il ceci:

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;}
}

Cette affiche:

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

L'approche suivante est problématique:

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

par exemple. si vous voulez vérifier si un objet dit de type

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

est de type

List<String> 

en fonction du résultat de l'approche getModelType précité (), par exemple:

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

elle se traduira par de faux alors qu'il devrait être vrai parce que les deux objets implémentent la liste d'interface (depuis getModelType () retourne un objet de classe de la liste de type et non ArrayList).

Voici une approche qui a fonctionné pour moi (un peu lourd, mais conduit à corriger les résultats dans l'exemple ci-dessus, pourrait être déplacé vers un initialiseur statique):

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];
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top