9
votes

Pourquoi la liste n'est-elle pas un sous-type de liste ?

Object o;
Double d;
String s;

o = s;
d = (Double) o;

3 commentaires

liée (pas un duplicate exact, bien que la bonne réponse soit fondamentalement la même): Stackoverflow.com/questions/251298/...


Le terme d'art est covariance - Je le mentionne car cela vous permet de la regarder, y compris sur le débordement de la pile (si vous voulez voir ce que je devais en dire à ce sujet - Le contexte de C #, mais il s'applique à Java tout aussi bien - rechercher [Utilisateur de covariance: 95810], par exemple).


Une double coulée comme wahey ((liste ) (liste ) Nouvelle ArrayList ()) compilera, bien que cela ne soit pas recommandé.


6 Réponses :


9
votes

considère si c'était ... xxx

Vous seriez capable d'ajouter quelque chose du type parent à la liste, ce qui pourrait ne pas être ce qu'il a été déclaré autrefois déclaré, ce qui, comme le Le dessus exemple montre, provoque toutes sortes de problèmes. Ainsi, il n'est pas permis.


3 commentaires

Ceci est correct, mais la question indique qu'il comprend déjà cela et veut savoir pourquoi la décision a été prise pour interdire ce comportement tout en permettant encore d'autres formes de comportement non dangereux.


J'ai déjà compris cet exemple. J'ai essayé d'expliquer ce scénario dans la question (comme dit Tyler), mais merci pour le commentaire.


Ce type de comportement dangereux réellement est autorisé avec des tableaux. Ce qui suit compile tout simplement bien mais génère une erreur d'exécution: objet [] arr = neuf entier [2]; arr [0] = "Oh non!";



11
votes

Ce que vous faites dans le exemple "sans génériques" est un casting, ce qui précise que vous faites quelque chose de type-danger. L'équivalent avec des génériques serait: xxx pré>

ce qui se comporte de la même manière (compile, mais échoue au moment de l'exécution). La raison de ne pas autoriser le comportement que vous posez est parce que cela permettrait aux les actions implicites em> de type-dangereuses, qui sont beaucoup plus difficiles à remarquer en code. Par exemple: P>

List<Double> list_d;
String s;

Foo(list_d, s);


1 commentaires

Ah, je vois. Merci beaucoup. :)



4
votes

Ils ne sont pas des sous-types les uns des autres en raison de leur fonctionnement des génériques. Ce que vous voulez, c'est de déclarer votre fonction comme ceci: xxx pré>

alors il acceptera une liste de tout ce qui étend tout objet. Vous pouvez également faire: p>

public void wahey(List<? extends Number> list) {}


2 commentaires

+1, voici comment fonctionne les génériques. DO Ramassez une copie des génériques et des collections Java. Livre génial!


Ce n'était pas ma question. Je sais que ce sont les règles de sous-tapage avec des génériques.



3
votes

Il y a essentiellement deux dimensions d'abstraction ici, l'abstraction de la liste et l'abstraction de son contenu. Il est parfaitement amende à varier le long de la liste abstraction - à dire, par exemple, qu'il s'agit d'une liste linité ou d'une arrachelist - mais ce n'est pas bien de restreindre le contenu, de dire: ceci (liste qui contient des objets) est une (liste liée qui contient). ne contient que des chiffres). Parce que toute référence qui le sait comme une (liste qui détient des objets) comprend, par le contrat de son type, qu'il peut contenir tout objet .

Ceci est assez différent de ce que vous avez fait dans le code d'exemple de non-génériques, où vous avez dit: Traitez cette chaîne comme si c'était un double. Vous êtes à la place d'essayer de dire: Traitez ceci (liste qui ne contient que des chiffres) en tant que (liste qui détient n'importe quoi). Et ce n'est pas le cas, et le compilateur peut le détecter, de sorte qu'il ne vous laisse pas sortir avec elle.


0 commentaires

1
votes

"Ce que nous faisons ici est essentiellement la même chose, sauf cela passera chèques de compilation et échec uniquement à Durée. La version avec les listes ne sera pas compiler. "

Ce que vous observez est parfaitement logique lorsque vous considérez que l'objectif principal des génériques Java est d'obtenir des incompatibilités de type pour échouer au moment de la compilation au lieu d'exécution.

de Java.sun.com

Generics fournit un moyen pour vous de Communiquer le type d'une collection au compilateur, de sorte qu'il puisse être vérifié. Une fois que le compilateur connaît la type d'élément de la collection, le COMPILER peut vérifier que vous avez utilisé la collection de manière cohérente et peut Insérez les mises correctes sur les valeurs être sorti de la collection.


0 commentaires

0
votes

en java, Liste code> n'est pas strong> un sous-type de la liste code> quand s code> est Un sous-type de t code>. Cette règle fournit la sécurité du type.

Disons que nous autorisons une liste list code> d'être un sous-type de Liste code>. Considérez l'exemple suivant: P>

class MyCollection<T> {
     // Now we allow all types S that are a subtype of T
     public void addAll(Collection<? extends T> otherCollection) {
         ...

         otherCollection.add(new S()); // ERROR! not allowed (Here S is a subtype of T)
     }
} 


0 commentaires