6
votes

Erreur de compilateur de Generics Java: Types incompatibles

Lorsque vous ne faites pas vraiment des choses fantaisistes avec Java, je suis venu une erreur avec des génériques que je n'ai pas pu comprendre pourquoi cela ne fonctionne pas. Le code est: xxx pré>

L'erreur que je reçois lors de la compilation est la suivante: p>

test/TestClass.java:11: incompatible types
found   : test.TestClass.E<test.TestClass.D<test.TestClass.A>>
required: test.TestClass.E<test.TestClass.D<? extends test.TestClass.C>>
      E<D<? extends C>> a = new E<D<A>>();
                            ^
test/TestClass.java:12: incompatible types
found   : test.TestClass.E<test.TestClass.D<? extends test.TestClass.C>>
required: test.TestClass.E<test.TestClass.D<? extends java.lang.Object>>
      E<D<? extends Object>> b = new E<D<? extends C>>();
                                 ^
test/TestClass.java:13: incompatible types
found   : test.TestClass.E<test.TestClass.D<test.TestClass.A>>
required: test.TestClass.E<test.TestClass.D<? extends test.TestClass.A>>
      E<D<? extends A>> c = new E<D<A>>();
                            ^
test/TestClass.java:14: incompatible types
found   : test.TestClass.E<test.TestClass.D<test.TestClass.A>>
required: test.TestClass.E<test.TestClass.D<? super test.TestClass.A>>
      E<D<? super A>> d = new E<D<A>>();
                          ^
4 errors


3 commentaires

C'est une bonne question pour la prochaine édition de Java Puzzlers Javapuzzlers.com


Je crois que tu es tombé sur un cas de bord. Très intéressant.


Cela peut être utile si vous pouvez avoir une idée de cela: bit.ly/3rrnv3


10 Réponses :


1
votes

Vérifiez le type de l'objet renvoyé par des tableaux.Aslist appel. Je voudrais devinez il renvoie une liste > objet, qui ne sera pas istable à une liste >.


2 commentaires

Regardez la nouvelle ligne que je viens de poster. Et pourquoi est-ce non castable?


Tout se résume à ce que j'ai commenté la réponse de Grzegorzoledzki. Les références vous permettraient d'utiliser une gamme de classes plus large que votre classe de génériques d'origine accepte.



2
votes

Peut-être que cela vous aiderait à comprendre: xxx

ceci ne compile pas non plus avec une erreur similaire.

EDIT: Consultez: http://www.ibm.com/developerworks/java/library/ j-jtp01255.html


1 commentaires

Cela ne compile pas, car en utilisant la référence Alist, vous seriez capable d'insérer des objets dans votre liste, mais il est censé contenir des cordes uniquement.



1
votes

Spécifie les limites supérieures du type, ce qui signifie que le type doit être étendu de C. est apparemment plus général, il est donc incompatible.

Pensez à ce cas d'utilisation. En spécifiant une limite supérieure, vous vous attendez à ce que certaines interfaces minimales soient mises en œuvre. Dis que vous avez un DOIT () Méthode déclarée dans C. Toute classe extension C aurait cette méthode mais pas tous les objets d'extension de la classe (c'est chaque classe en Java).


3 commentaires

Vous avez le mauvais chemin, j'essaie d'assigner à


Vous devrez peut-être penser à un mauvais moyen :) C'est exactement l'opposé de la sécurité de type d'affectation d'objet.


Ni le travaillerait non plus, si cela a du sens ou non. Les types génériques doivent correspondre exactement, pas seulement en étendant les types.



0
votes

C'est pire que ça. Vous ne pouvez même pas faire cela:

List<D<? extends C>> a = Arrays.asList(new D<A>(), new D<B>()); //compiles
List<D<? extends Object>> b = a; //error


0 commentaires

2
votes

Ceci est fondamentalement le même cas que posté précédent. Fondamentalement, dans un cas de génériques, vous n'êtes jamais autorisé à faire cette décision:

pense à cet exemple: p> xxx pré>

ceci ne compile pas car il n'est pas en sécurité . Vous pourriez éventuellement ajouter des chaînes Alist. Vous essayez d'attribuer une liste d'objets qui sont garantis à des chiffres, mais peuvent être n'importe quel numéro, à une liste qui vous garantit uniquement que vous contiendrez des objets, mais qui peuvent être des objets. Si le compilateur a permis ce cas, il desserrerait la restriction sur laquelle les types d'objets sont autorisés à entrer dans la liste. C'est pourquoi vous devez utiliser le caractère générique?, En tant que tel: p> xxx pré>

au compilateur arraylist Extend Object> code> signifie "une arracheliste de type spécifique"? " que je ne sais pas, mais que je sais étend votre objet. Cette arrayliste est garantie de ne contenir que des éléments de cet inconnu "?" type, et ne contient donc que des objets ». Dans ce cas, le compilateur ne vous permettra toutefois pas de faire Alist.Ajouter (2). Pourquoi est-ce le cas, car le compilateur ne connaît pas le type des éléments de la liste et que vous ne pouvez pas vous garantir que vous êtes autorisé à insérer des objets entier. P>

Vous avez raison de penser que d Extend Object> Code> est un super-type de d s'étend c> code>. Cependant, liste > Code> n'est pas un sous-type de la liste > CODE>, vous devez utiliser Liste s'étend d s'étend c >> code>. p>

Votre cas est essentiellement équivalent à p> xxx pré>

Vous avez le même problème que ci-dessus, la liste à droite La face ne peut contenir que l'objet de la classe D, dont le paramètre type est C, et vous essayez d'assigner à une liste (du côté gauche) peut contenir des objets de la classe D de la classe D dont le paramètre type peut être n'importe quel objet. P>

Donc, si le compilateur a permis à votre code ne serait pas sécurisé et que ce qui suit échouerait. P>

// type parameter of left hand side is ? extends subtype
List<? extends D<? extends Object>> b = Arrays.asList(new D<A>(), new D<B>()); 

// type parameter of left hand side is identical
List<D<? extends C>> b = Arrays.asList(new D<A>(), new D<B>());

// type parameter of left hand side is ? extends subtype
List<? extends D<? extends C>> c = Arrays.asList(new D<A>());

// type parameter of left hand side is identical
List<D<A>> c = Arrays.asList(new D<A>());


0 commentaires

0
votes

La chose est que list > définit fondamentalement une nouvelle classe et donc liste > . Même lorsque C étend un objet qui ne signifie pas que liste > étend list > et ce serait nécessaire pour que l'assidation fonctionne.

althoug this Série d'articles est écrit pour la plate-forme .NET La description du problème est toujours vraie pour Java Generics


1 commentaires

Vous devez échapper à ces supports d'angle avec des backticks.



0
votes

Vous ne pouvez pas hériter dans le paramètre générique. Dites que vous avez suivi des références suivantes: xxx pré>

Vous affectez maintenant la même liste: A = B; p>

Si un code est le suivant: P>

String s = b.get(0);


0 commentaires

-1
votes

Nope.
n'est pas la même chose que
Si c'était le cas, cela mènerait également l'hypothèse (non déclarée) - C étend un objet, et conduisait à dire ...

Classe C {Public Void DosomethermandeDentillante (); };

liste AllatSea = New ArrayList <...> (); Liste Allobjects = New ArrayList <...> (); allObject.add (nouveau entier (88)); ...

AllatSea.addall (Allobjects); ...

AllatSea.get (...). Dosomethingmaningful (...); // uh-oh .. cela trouve l'entier 88


Le C ++ FAQ fournit un exemple lucide pour cela à 21,3


3 commentaires

Je ne pense pas qu'un exemple C ++ aide dans une question Java.


Je vous prie de différer, si la liste est la même que la liste de quelque chose - d'autre concerne la compréhension de l'héritage et la substituabilité.
que, imo, concerne les fondements OO; Par conséquent, la référence à C ++ devrait être acceptable


L'exemple n'est toujours pas correct (ou même aide, imo). La ligne ALTATEA.ADDALL () ne compile pas, et l'AllObject.Ajoud ().



0
votes

Je pense que cela sera plus clair si nous étendons votre exemple. Mettons des fonctionnalités dans e et élaborer sur la première ligne de votre méthode principale: xxx

La dernière ligne de la nouvelle méthode principale est la raison pour laquelle A1 ne peut pas être réglé sur A2. Si le compilateur vous laissait faire cela, vous seriez peut-être en mesure de mettre un d dans un conteneur qui a été déclaré ne contenant que d s.

La raison en n'est pas évidente de Votre exemple original est dû au fait que vous n'avez pas créé une variable distincte qui a référencé l'objet à l'aide de la typographie plus restrictive E >. Mais j'espère que maintenant vous pouvez voir que si une telle référence existe, sa sécurité de type serait compromise par la cession que vous avez essayée de faire.


0 commentaires