9
votes

Comment écrire une méthode générique qui prend deux arguments des mêmes types en Java?

J'ai été très surpris lorsque j'ai remarqué que le code suivant compile sans avertissements et impressions integer / chaîne : xxx

Je m'attendais à une erreur de compilation.

y a-t-il une raison pour laquelle ce code compile?

Quel est le moyen correct de s'assurer que les arguments ont le même type?

EDIT: sur les paramètres de type bornés? Le mieux que je puisse penser est celui-ci: xxx

Malheureusement, Java n'autorise pas les contraintes cycliques. ne compile pas. Est-ce une impasse?


1 commentaires

Vous pouvez indiquer le type générique lorsque vous appelez la méthode: genericstest. méthode (1, "1"); // ne compilera pas


4 Réponses :


7
votes

La raison pour laquelle cela compile est parce que Java déduira la super-type la plus spécifique des arguments passés dans ce cas, dans ce cas, objet code> s> sérialisable et comparable s'étend sérialisable et comparable s'étend comparable >>> code>, après 1 code> est en boîte sur integer code> et "1" code> est transmis comme un Chaîne code>.

sans génériques: p> xxx pré>

même sans génériques, vous pouvez passer dans un entier code> et un double code>. p>

Seulement si le type en question est final code> pouvez-vous faire cela, sans génériques: p>

public void method(MyFinalClass arg1, MyFinalClass arg2) {
    // Yes, they're both MyFinalClasses
}


1 commentaires

Java déduit en fait le Superype sérialisable et comparable >> dans ce cas.



1
votes

Il n'est pas possible de le faire. Ou de la regarder d'une autre manière, deux arguments de référence sont toujours "le même type" - objet - Tous les arguments de type de référence sont toujours des instances de objet .

t peut toujours être objet et prendre deux arguments de référence. Même avec méthode de vide (t arg1, u arg2) , t et u peut être objet et prenez donc deux arguments à nouveau.

La raison sous-jacente à cet égard est qu'il n'ya pas de raison de sécurité pour avoir une telle contrainte. L'un des principaux points d'héritage est qu'il devrait être possible de traiter des instances de sous-classe comme une instance de superclasse en toute sécurité. Un type de référence de type superclasse peut indiquer une instance de cette classe ou sous-classe librement. Par conséquent, deux variables de référence qui ont le même type de compilation, peuvent toujours pointer sur l'exécution à des instances de différents types de sous-classes, totalement en toute sécurité. Donc, vous ne pouvez jamais, lors de la compilation, faire une déclaration sur la relation des classes d'exécution réelles de deux cas, autres que ce sont des sous-classes du type de temps de compilation. Comme il est prudent pour les deux arguments d'être des cas de différentes classes au moment de l'exécution, il peut être moins sûr de passer deux arguments de différents types de temps de compilation.


0 commentaires

4
votes

Vous pouvez ajouter la classe sous forme de paramètre supplémentaire.

private static <T> void method(T arg1, T arg2, Class<T> type) {
    // ...
}


0 commentaires

0
votes

Voici comment j'ai résolu ce problème - je voulais créer une méthode qui crée un diff de deux objets.

Liste publique getchanges (objet o1, objet O2);

Naturellement, je voulais que l'O1 et O2 soient du même type. J'ai résolu ceci en encapsulant cette méthode à l'intérieur d'une classe paramétré. xxx

Ceci peut être utilisé comme: Liste Modifications = nouveau diff générateur (). Getchanges (MyClassold, MyClassnew);


0 commentaires