Java casting dans les interfaces
Quelqu'un peut-il m'expliquer comment le compilateur ne se plaint pas de la première coulée, mais ne se plaignent dans le deuxième?
interface I1 { }
interface I2 { }
class C1 implements I1 { }
class C2 implements I2 { }
public class Test{
public static void main(){
C1 o1 = new C1();
C2 o2 = new C2();
Integer o3 = new Integer(4);
I2 x = (I2)o1; //compiler does not complain
I2 y = (I2)o3; //compiler complains here !!
}
}
- Par l'exécution de cette, vous rencontrerez
ClassCastException
, qui est unRuntimeException
. - vous avez tort
- Où ai-je tort?
- L'OP a dit que le compilateur se plaint suggérant à moi que vous n'obtenez pas une chance pour l'exécuter.
- même s'il pouvait l'obtenir à compiler par la fixation de l'élément qui a eu une erreur de compilation, la ligne ci-dessus, il aurait provoqué une
ClassCastException
. - Vous avez tort parce que vous parlez de choses que vous ne devriez pas. L'eau est mouillée. Mais il est faux de parler de ce problème dans ce contexte. Ok? Évidemment, la question de savoir à ce sujet parce qu'il fait une expérience.
- La raison pour laquelle je demande parce que je ne pouvais pas comprendre pourquoi le compilateur se comporte différemment dans ces deux cas. Maintenant, il fait sens. Merci!!
- l'eau est humide ne fait pas de sens. L'eau est liquide. Il peut sembler évident pour beaucoup, mais on ne peut pas simplement supposer que cela est évident pour tout le monde. Plutôt, nous amener à l'évidence pour des précisions au lieu de le laisser glisser.
Vous devez vous connecter pour publier un commentaire.
Lorsque vous lancez
o1
eto3
avec(I2)
, vous dire au compilateur que la classe de l'objet est en fait une sous-classe de son type déclaré, et que cette sous-classe implémenteI2
.La
Integer
classe est final, donco3
ne peut pas être une instance d'une sous-classe deInteger
: le compilateur sait que vous mentez.C1
n'est cependant pas définitif, donco1
pourrait être une instance d'un sous-type deC1
qui implémenteI2
.Si vous faites
C1
final, le compilateur va se plaindre de trop:Integer
est définitive (ce qui est évident pour vous et moi, mais probablement pas pour tout le monde) et le "n'a aucune chance d'être une interface" la partie de ne pas y mettre trop d'informations; en fait, l'info en question est caché dans la deuxième phrase. On pourrait même penser qu'final
classes ne peuvent pas mettre en œuvre des inferfaces qui n'est pas vrai.Selon JLS chapitre 5
5.5.1. Type De Référence De La Coulée
C'est parce que la classe
Integer
est définitive etC1
ne l'est pas. Ainsi, un objet Integer ne peut pas mettre en œuvre I2, tandis qu'une C1 de l'objet, s'il est une instance d'une sous-classe de la C1 qui implémente I2.Selon JLS 5.5.1 - Type de Référence de la coulée, la règle(s) s'appliquent:
Si T est un type de classe, alors |S| <: |T| ou |T| <: |S|. Sinon, une erreur de compilation se produit.
I2 y = (I2)o3; //compiler complains here !!
Dans ce cas, un
Integer
etI2
sont sans rapport avec en aucune manière, une erreur de compilation se produit. Aussi, parce queInteger
estfinal
, il n'y a aucun rapport entreInteger
etI2
.I2
etI1
peuvent être liées en raison à la fois d'être un marqueur de l'interface (il n'y a pas de contrat).Comme pour le code compilé, la règle suivante:
S
esto1
etT
estI2
.Espère que cette aide.