8
votes

Que signifie vraiment Wildcard Wildcard de paramètres Java? Quelle est la vraie différence entre FOO et FOO ?

pour une interface générique: xxx pré>

la différence entre les deux champs: p> xxx pré>

est que foo2 code > est un type générique et foo code> n'est pas. Étant donné que ? Code> est un caractère générique (que je pense que tout type) et que chaque type est un sous-type d'objet, alors je m'attends à ce que j'attends FOO > Code> et et et FOO code> à l'équivalent sémantiquement et syntaxiquement. p>

Cependant, consultez les éléments suivants: P>

public class Puzzler {
    void f() {
        Integer i = null; 
        Foo<?> foo1 = null;
        foo1.foo(i); // ERROR 
        Foo foo2 = null; 
        foo2.foo(i); // OKAY
        Foo<Integer> foo3 = null; 
        foo3.foo(i); // OKAY 
        Foo<Object> foo4 = null; 
        foo4.foo(i); // OKAY
    }

    private interface Foo<T> {
        void foo(T t);
    } 
}


4 commentaires

En supposant que ce sont des erreurs de compilation?


@andrewcooke ce code serait valide; Cependant, étant donné que l'objet serait stocké dans une variable FOO , il ne saurait pas sur le paramètre string . Par conséquent, si foo a des méthodes qui prennent des arguments de type t , la seule valeur autorisée serait null , et s'il a des méthodes que Retour t , il est traité comme objet .


Désolé, j'ai supprimé mon commentaire avant de voir votre réponse. suis maintenant confus. Quand le travail de capture fonctionne-t-il?


Oh, d'accord, Capture ne correspond que exactement avec lui-même. C'est évident maintenant je vois l'erreur du compilateur dans un code de test ...


5 Réponses :


6
votes

foo > code> est sémantiquement la même chose que foo Extend Object> Code>: C'est un FOO code> avec le paramètre de type de quelque chose spécifique, mais la seule chose à propos de "quelque chose" est que c'est une sous-classe de objet code> (qui ne dit pas trop, car toutes les classes sont des sous-classes de objet code>). foo code>, d'autre part, est un foo code> avec le paramètre de type spécifiquement objet code>. Tandis que tout est compatible avec objet code>, tout n'est pas compatible avec ? Code> où ? Code> étend objet code> .

Voici un exemple de pourquoi FOO > code> devrait générer une erreur: p> xxx pré>

modifie maintenant votre exemple à ceci: p > xxx pré>

puisque i code> est un integer code>, il n'y a aucun moyen que le compilateur devrait autoriser foo1.foo (i) Pour compiler. P>

Notez que P>

Foo<Object> foo4 = new StringFoo();


3 commentaires

Compilateurs ne peut pas traiter les types bruts comme des erreurs, voir le JLS


@Daniel - En Eclipse, vous pouvez définir le compilateur pour traiter l'utilisation de types bruts comme erreurs. Vous pouvez également définir la plupart des compilateurs pour traiter tous les avertissements comme étant des erreurs et des compilateurs peuvent certainement avertir l'utilisation des types bruts.


Elaborer: Si vous utilisez foo comme type brut (c'est-à-dire sans paramètre de type), cela (a) générera un avertissement de compilation (que vous pouvez Ignorer), (b) Cause Le compilateur d'utiliser objet pour tous les types génériques et (c) empêchent le compilateur de vérifier les paramètres de type pour l'exactitude dans le contexte d'autres génériques. Par exemple, foo f = nouveau foo (); est une erreur de compilation, mais foo f = nouveau foo (); Compilera (avec un avertissement), puis soulevez un Classcastexception au moment de l'exécution si les types sont faux. Ceci est indésirable, alors n'utilisez pas de types bruts.



0
votes

Eh bien, en raison de l'effacement de type, tout ce qui est liée aux génériques est compilé uniquement; Je suppose que c'est ce que vous appelez syntaxtique.
Je pense que votre évaluation initiale est correcte et la différence réelle est que cela en fait une variable typée générique et la FOO ordinaire.


0 commentaires

1
votes

Considérez ces types:

  • Liste
  • Liste
  • Liste

    même si string est un sous-type de charcuternence qui est un sous-type de objet , ces types de liste n'ont pas de Relations de sous-type-Superype. (Curieusement, string [] est un sous-type de Chaluquant (] qui est un sous-type de objet [] , Mais c'est pour des raisons historiques.)

    Supposons que nous voulions écrire une méthode qui imprime une liste. Si nous faisons xxx

    Ceci ne pourra pas imprimer une liste (sans hacks), depuis une liste n'est pas une liste . Mais avec des caractères génériques, nous pouvons écrire xxx

    et transmettre n'importe quelle liste.

    wildcards peut avoir des limites supérieure et inférieure pour une flexibilité supplémentaire. Disons que nous voulons imprimer une liste qui ne contient que charcuternence s. Si nous faisons xxx

    , nous rencontrons le même problème - nous ne pouvons que le transmettre une liste et notre liste n'est pas une liste . Mais si nous faisons plutôt xxx

    , nous pouvons transmettre cette liste list et une liste , et ainsi de suite.


0 commentaires

0
votes

L'objet est le Superype de tous types de Java. Cependant, FOO n'est pas le super-espèce de tous foo. Le superype de tous foo est foo. Voir http://docs.oracle.com/javase/Tutorial/extra/ Generics / Wildcards.html Pour plus de détails.


0 commentaires

0
votes

Le caractère générique dans foo indique que dans la portée actuelle, vous ne savez pas ou ne vous souciez pas de quel type de 'foo' vous avez.

FOO et foo sont les mêmes (le premier est sténographique pour l'autre). foo est différent.

un exemple concret :

Vous pouvez attribuer n'importe lequel Sorte de Liste à la liste par exemple xxx

si vous avez une liste Vous pouvez appeler taille () parce que vous n'avez pas besoin de Pour savoir quel type de liste il est de trouver sa taille. Et vous pouvez appeler obtenir (i) car nous savons que la liste contient une sorte d'objet , le compilateur le traitera comme si obtenir retour et objet .
Mais vous ne pouvez pas appeler ajouter (o) car vous ne savez pas (et que le compilateur ne sait pas) Quel type de liste que vous avez affaire.
Dans notre exemple ci-dessus, vous ne voudriez pas autoriser list1.add (nouvel objet ()); parce que c'est censé être une liste de chaîne s < P> La raison des caractères génériques est donc vous pouvez faire des choses comme ceci: xxx

Ce code peut fonctionner sur n'importe quel type de liste souhaitée, une liste , list , , , etc.

si la signature était Statique Boolean contenant (Liste Liste) Vous ne pouviez ensuite réussir que list à celui-ci, list ne fonctionnerait pas.


0 commentaires