Incompatibilité de Type d'une Classe de médicaments Génériques
J'ai le code suivant ne compile pas et même si il y a un moyen de faire de la compilation je veux comprendre pourquoi il n'est pas de la compilation. Quelqu'un peut-il m'éclairer quant à la raison précise pour laquelle je reçois le message d'erreur, je vais poster à la fin s'il vous plaît?
public class Test {
public static void main(String args[]) {
Test t = new Test();
t.testT(null);
}
public <T extends Test> void testT(Class<T> type) {
Class<T> testType = type == null ? Test.class : type; //Error here
System.out.println(testType);
}
}
Type mismatch: cannot convert from Class<capture#1-of ? extends Test> to Class<T>
Par coulée Test.class
à Class<T>
cette compile avec un Unchecked cast
avertissement et fonctionne parfaitement.
Vous devez vous connecter pour publier un commentaire.
La raison en est que Test.class est de la Classe de type<Test>. Vous ne pouvez pas affecter une référence de Classe de type<Test> pour une variable de type Classe<T> comme ils ne sont pas la même chose. Toutefois, cela fonctionne:
Le caractère générique permet à la fois de la Classe<T> et de Classe,<Test> les références à être affecté à testType.
Il y a une tonne d'informations à propos de Java génériques de comportement à Angelika Langer Java Génériques FAQ. Je vais vous donner un exemple, en fonction des informations qui utilise le
Number
hiérarchie de classe Java de l'API de base.Envisager la méthode suivante:
C'est pour permettre les instructions suivantes pour être compiler avec succès:
Mais le suivant ne compile pas:
Maintenant, considérons ces instructions:
La deuxième ligne ne parvient pas à compiler et produit cette erreur
Type mismatch: cannot convert from Class<Number> to Class<Integer>
. MaisInteger
s'étendNumber
, alors pourquoi est-il un échec? Regardez ces deux prochaines déclarations de voir pourquoi:Il est assez facile de voir pourquoi le 2e ligne ne compile pas ici. Vous ne pouvez pas affecter une instance de
Number
à une variable de typeInteger
car il n'existe aucun moyen de garantir que leNumber
instance d'un type compatible. Dans cet exemple, leNumber
est en fait unLong
, qui ne peut certainement pas être attribué à unInteger
. En fait, l'erreur est aussi une incompatibilité de type:Type mismatch: cannot convert from Number to Integer
.La règle est qu'une instance ne peut pas être affectée à une variable qui est une sous-classe du type de l'instance qu'il n'y a pas de garantie, ce qui est compatible.
Génériques se comportent d'une manière similaire. Dans le générique de la signature de la méthode,
T
est juste un espace réservé pour indiquer que la méthode permet au compilateur. Lorsque le compilateur rencontretestNumber(Integer.class)
il remplace essentiellementT
avecInteger
.Jokers ajouter plus de flexibilité, comme la suite va le compiler:
Depuis
Class<? extends Number>
indique quelque type que ce soitNumber
ou une sous-classe deNumber
c'est parfaitement légal et potentiellement utile dans de nombreuses circonstances.Class<Test>
àClass<T>
, siT
doit s'étendreTest
? N'est-ce pasClass<Test>
un cas deClass<T extends Test>
, polymorphically?T
n'est pas un générique, c'est un placehoder pour un type qui le compilateur, dans l'essence, les produits de substitution lors de la compilation du code. La syntaxe générique permet pour de plus larges attributions puisqu'il n'a pas contraindre la déclaration de la même manière. Je vais essayer d'ajouter un exemple pour ma réponse plus tard.Supposons que j'étends Test:
Maintenant, lorsque j'ai invoqué
testT
, le paramètre de type<T>
estSubTest
, ce qui signifie que la variabletestType
est unClass<SubTest>
.Test.class
est de typeClass<Test>
, ce qui n'est pas cessible à une variable de typeClass<SubTest>
.Déclarer la variable
testType
comme unClass<? extends Test>
est la bonne solution; casting pourClass<T>
se cache un réel problème.Supprimer la condition, et l'erreur est un peu plus agréable...