Java Casting Interface à la classe
public class InterfaceCasting {
private static class A{}
public static void main(String[] args) {
A a = new A();
Serializable serializable = new Serializable(){};
a = (A)serializable;
}
}
Compilation réussir, mais en Runtime exception
Exception in thread "main" java.lang.ClassCastException: InterfaceCasting$1 cannot be cast to InterfaceCasting$A
POURQUOI COMPILATION RÉUSSIR? Compilateur doit connu que serialiazable n'est pas Un?
source d'informationauteur komenan
Vous devez vous connecter pour publier un commentaire.
Comme vous le soulignez, ce sera compiler:
Ce cependant, sera de pas compiler:
Donc, ce qui se passe ici? Quelle est la différence?
Bien, depuis
MyInterface
est simplement une interface, il pourrait très bien être mis en œuvre par une classe qui étend laauquel cas la distribution deMyInterface
àA
serait légale.Ce code par exemple, réussir à 50% de toutes les exécutionset illustre le fait que le compilateur aurait besoin pour résoudre éventuellement indécidable problèmes dans le but de toujours "détecter" illégal jette au moment de la compilation.
Java langage de spécification unis, que:
Et, plus tard, sur le spectacle Les règles détaillées pour la compilation de la légalité d'un casting de conversion d'une valeur au moment de la compilation de référence de type S, à un moment de la compilation de référence de type T - méfiez-vous, ils sont très complexes et difficiles à comprendre.
La règle intéressante est:
Dans votre exemple, il est parfaitement clair que le casting est illégal. Mais réfléchissez à ce léger changement:
Maintenant un plâtre à partir d'un
Serializable
àA
est possible au moment de l'exécution, ce qui montre que, dans ces cas, il est préférable de confier l'exécution de décider si nous pouvons exprimer ou pas.Que pour le compilateur, la variable serializable peut contenir n'importe quel objet qui implémente
Serializable
qui comprend les sous-classes deA
. Donc, il suppose que vous savez que les variables, en effet, contient unA
objet et qui permet de ligne.Le compilateur n'est pas assez intelligent pour retracer les origines de
serializable
et réaliser qu'il ne peut jamais être de typeA
. - Il vraiment évalue seulement la ligne:et voit que
serializable
une référence de typeSerializable
mais il peut faire référence à une classe qui aussi est de typeA
. La classe réelle queserializable
références n'est pas connue jusqu'à ce moment de l'exécution.Dans ce cas trivial, nous savons que cette distribution ne réussira jamais, mais en général ce n'est pas qu'un problème d'exécution que les différents chemins de code qui peut conduire à un casting sont (en théorie) à l'infini.
Si vous voulez éviter ce problème lors de l'exécution, vous pouvez le tester pour elle..
Il ne peut pas savoir que, parce que le temps de compilation type de
serializable
estSerializable
.Pour illustrer, considérons ceci:
c'est exactement comme votre question, il compile.
cela ne compile pas car
b
n'est pas unA
.Alors que je ne connais pas la réponse correcte, il n'est généralement pas une bonne idée de jeter une interface à une classe, et ce pour plusieurs raisons.
a) une interface définit un contrat, c'est la garantie de comportement. Une classe peut définir plus de ce contrat, l'utilisation des autres méthodes peuvent avoir des effets secondaires inattendus et de briser l'Api. E. g. lorsqu'une méthode est passée à une liste et vous découvrez le passé de l'objet est en fait une LinkedList et vous le lancez et l'utilisation de la File d'attente basé sur des méthodes qu'il définit également, vous êtes en rupture de l'API.
b) en outre, l'objet avec l'interface peut ne pas être une "vraie" de l'objet au moment de l'exécution, mais peut-être un service de proxy créé autour de l'objet d'origine par une bibliothèque comme le Printemps ou EJB. Votre distribution vont échouer dans ces cas.
Si vous devez absolument en fonte, de ne jamais le faire sans un instanceof vérifier:
Source :
JLS : les Conversions et les Promotions
Serializable
n'est PAS unA
de sorte qu'il jetteClassCastException
.