2009-11-27 6 views
3

Impossible de comprendre ce problème de génériques. J'ai ces interfaces:Problème de génériques Java avec la classe

public interface LoadableObject 
{ 
} 
public interface LoadableObjectFactory<T> 
{ 
} 

Et maintenant, je veux faire:

public class ObjectReference<T extends LoadableObject> 
{ 
    Class<? extends LoadableObjectFactory<T>> _cls; 

    public ObjectReference(LoadableObjectFactory<T> obj) 
    { 
     _cls = obj.getClass(); 
    } 
} 

Mais je reçois une erreur:

incompatible types 
found : java.lang.Class<capture#885 of ? extends test.LoadableObjectFactory> 
required: java.lang.Class<? extends test.LoadableObjectFactory<T>> 
    _cls = obj.getClass(); 
        ^

Je suis en mesure de compiler si je supprimer le type params pour LoadableObjectFactory à la définition de _cls, mais alors c'est un type incomplet ... Y a-t-il quelque chose qui me manque ou est-ce simplement impossible?

+0

On dirait une autre victime d'effacement de type, mais je ne suis pas en mesure de vérifier tout de suite. –

+0

Je voudrais une explication pour ce que vous essayez vraiment de faire ici, parce qu'à première vue, cette conception n'a aucun sens pour moi. Je comprends Loadable et LoadableFactory, mais que fait la classe de référence pour vous, et pourquoi doit-elle avoir une fabrique en tant que membre de données privé? – duffymo

+0

Merci à tous pour vos réponses tous m'ont été utiles! Quant à ce que j'essaie de faire, je ne vais pas entrer dans les détails, mais l'échantillon que vous voyez n'a pas tous les détails désagréables que j'ai dans mon code et je ne veux pas vous faire mal au cerveau pour essayer de comprendre toutes les raisons derrière cela :). Je voulais juste savoir quoi en faire. Donc, maintenant que je comprends - Java est faux, mais java est en train de compiler donc je vais devoir m'en occuper;). – inkredibl

Répondre

4

getClass() en runtime fournit la classe <? >. En raison de l'effacement de type, les informations sur les paramètres génériques ne sont pas disponibles. Vous devez faire un casting

@SuppressWarnings("unchecked") 
public ObjectReference(LoadableObjectFactory<T> obj) 
{ 
    _cls = (Class<? extends LoadableObjectFactory<T>>) obj.getClass(); 
} 

pour le faire fonctionner

+0

Je ne vois pas comment cela est applicable - il s'agit probablement d'une erreur de compilation, et à la compilation toutes les informations de type disponibles. JavaDoc pour 'Object.getClass' a même ce bit:" Le type de résultat réel est Class où | X | est l'effacement du type statique de l'expression sur laquelle getClass est appelée. la conversion est obligatoire dans ce fragment de code: 'Nombre n = 0; Classe c = n.getClass();' " –

+0

Oui, vous avez raison. C'est probablement une erreur de compilation. Néanmoins, le casting est un moyen de le contourner. –

+0

erreur de compilation? "... | X | est l'effacement ** du type statique ...". Le code d'origine renvoie "Class ', après que' 'a été effacé. –

4

Voici le info about type erasure, directement de la bouche du cheval, pour ainsi dire. Ce truc me fait mal à la tête, alors je n'essaierai pas de l'expliquer. Il suffit de dire qu'il y a certaines opérations que vous attendez de travailler, mais parce que Java "oublie" les détails génériques des types entre les modules, ils ne le font pas.

Vous n'êtes probablement pas en mesure d'utiliser cette information, mais la même personne qui a créé des génériques dans Java est allée et a conçu un tout nouveau langage semblable à Java: Il s'appelle Scala. Scala gère les types et les génériques avec beaucoup plus de compétence; on pourrait dire que tout va bien à cet égard. Il fonctionne également dans la JVM et vous pouvez appeler entre les classes Scala et Java. Cependant, ce que je retiens personnellement de Scala, c'est qu'il s'agit d'un système permettant de gérer astucieusement des types complexes qui, accessoirement, peuvent également être utilisés comme langage de programmation. :)

1

Je ne pointerai pas du doigt l'effacement du type. Regardez le code statiquement, il est évidemment sûr, et il devrait passer le compilateur dans un monde meilleur. Les génériques de Java sont trop compliqués, ne valant pas votre temps pour comprendre tous les derniers détails. Si vous savez que vous savez mieux que le compilateur, faites juste ce qu'il faut pour le contourner.

0

Je me serais attendu à la LoadableObjectFactory ressembler à ceci:

public interface LoadableObjectFactory<T extends LoadableObject> 

Ceci étant dit - Object.getClass() retourne une classe typées, donc vous devez le jeter. Pour résoudre ce problème, l'aurait d'avoir changé la signature de java.lang.Object à

class Object<T extends Object<T>> { 
    native Class<T> getClass(); 
} 

mais des modifications à java.lang.Object aurait impliqué une intervention chirurgicale assez importante à peu près partout.

Questions connexes