incompatible types de frais et de type de variable
J'ai le compilation message:
[javac] ... error: incompatible types
[javac] exceptionClassHolder = new Holder<>( (new Exception()).getClass() );
[javac] ^
[javac] required: Holder<Class<? extends Exception>>
[javac] found: Holder<Class<CAP#1>>
[javac] where CAP#1 is a fresh type-variable:
[javac] CAP#1 extends Exception from capture of ? extends Exception
[javac] 1 error
Il me semble que la fonction du message, tout devrait être correct. CAP#1
en effet s'étend Exception. Alors, comment devriez-le message ci-dessus, être compris? SSCCE ci-dessous (initialement pas posté depuis que j'ai été en espérant pour comprendre le message d'erreur lui-même dans le cas général):
class Holder<T> {
public T t;
public Holder(T t) {
this.t = t;
}
}
public class FooMain {
public static void main(String args[]) throws Exception {
Holder<Class<? extends Exception>> exceptionClassHolder;
exceptionClassHolder = new Holder<>( (new Exception()).getClass() );
}
}
Nous montrer le code
OK je vais essayer de le reproduire d'abord dans une moindre situation
OK je vais essayer de le reproduire d'abord dans une moindre situation
OriginalL'auteur Marcus Junius Brutus | 2013-12-12
Vous devez vous connecter pour publier un commentaire.
Malheureusement, les réponses de ne pas expliquer ce qui se passe ici. Tout d'abord, la solution est tout simplement de spécifier le type de l'argument de
Holder
:La raison que votre version n'a pas de travail est parce que
new Exception().getClass()
renvoie uneClass<? extends Exception>
, où?
est un générique de capture (dénommé dans le compilateur message d'erreur commeCAP#1
). Puisque vous utilisez le "diamant" d'opérateur avecnew Holder<>
, le compilateur déduitClass<CAP#1 extends Exception>
pourT
et doncHolder<Class<CAP#1 extends Exception>>
est le type de l'objet créé.Toutefois, cela ne correspond pas à votre type déclaré de
Holder<Class<? extends Exception>>
. Il utilise un imbriqués générique, qui n'a pas de capture: alors queCAP#1 extends Exception
est certains type spécifique l'extension deException
, imbriquée? extends Exception
représente littéralement tout type l'extension deException
.Et tout
Class<CAP#1 extends Exception>
est un sous-type deClass<? extends Exception>
,Holder<Class<CAP#1 extends Exception>>
n'est pas un sous-type deHolder<Class<? extends Exception>>
parce que les génériques ne sont pas covariante, de sorte que la mission échoue.En spécifiant manuellement
Class<? extends Exception>
pourT
, vous aider le compilateur à éviter ce "piège".Voir mes réponses semblables sur ces postes:
Il est déduit par le compilateur, mais pas "correctement" - l'inférence qui donne la priorité à l'argument du constructeur sur la variable. Et il l'a fait échouer au moment de la compilation.
Intéressant. J'ai seulement regardé le type de retour de l'Objet.getClass() et non pas sur le texte de la documentation, qui a en effet dit que le type retourné est
Class<? extends Exception>
. Suis-je en droit de penser que c'est un cas très particulier d'un traitement spécifique par le compilateur, et qu'il n'est pas possible de faire ce que getClass() ne régulier de code Java?C'est exactement ça, désolé de ne pas élaborer plus tôt.
Je préfère encore la solution par Joop Eggen, puisque c'est ce qui permet d'utiliser le diamant de l'opérateur et de la laideur est caché dans un seul endroit. Cependant, je suis de l'acceptation de votre réponse à ma question a été formulée afin d'obtenir des informations sur la compréhension du message et le message d'erreur et pas tellement sur la solution à appliquer.
OriginalL'auteur Paul Bellora
La raison en est que
Exception.class
mais un objet d'Exception, java pense? extends Exception
est nécessaire.getClass()
, de nouveau? extends Class
nécessaire, si la Classe est définitive.Certainement un jour, ce sera simplifiée.
ma solution fonctionne avec le diamant de l'opérateur (comme demandé). La lecture de votre réponse excellent (mon +1), on reçoit l'impression qu'un diamant opérateur ne doit pas travailler. Comme vous semblez avoir, j'ai un langage de programmation/compilateur construction d'arrière-plan, de sorte que vous pourriez ellaborate un peu plus. Merci.
Vous avez raison que le diamant opérateur fonctionne lors de l'affectation à
Holder<? extends Class<? extends Exception>>
- c'est parce que ce type est cessible deHolder<Class<CAP#1 extends Exception>>
, contrairement àHolder<Class<? extends Exception>>
. L'inférence de type processus est toujours le même - le compilateur donne la priorité à l'argument du constructeur et en déduitClass<CAP#1 extends Exception>
pourT
.Je voulais souligner que l'utilisation
Holder<? extends Class<? extends Exception>>
est inutile, car il limiteexceptionClassHolder
d'être un "producteur" seulement, ce qui pourrait ne pas être souhaitable.OriginalL'auteur Joop Eggen