81 votes

Java casting dans les interfaces

Quelqu'un peut-il m'expliquer s'il vous plaît comment le compilateur ne se plaint pas dans le premier casting, mais se plaint dans le second?

 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 !!
     }
}
 

152voto

WilQu Points 3010

Lorsque vous lancez o1 et o3 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émente I2.

L' Integer classe est définitive, alors o3 ne peut pas être une instance d'une sous-classe de Integer: le compilateur sait que vous mentez. C1 n'est cependant pas définitive, donc, o1 pourrait être une instance d'un sous-type d' C1 qui implémente I2.

Si vous effectuez C1 finale, le compilateur va se plaindre de trop:

interface I1 { }
interface I2 { }
final 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 y = (I2)o3; //compiler complains here !!
        I2 x = (I2)o1; //compiler complains too
     }
}

37voto

maba Points 15744

Selon JLS chapitre 5

5.5.1. Référence Type Coulée De

Donné au moment de la compilation de référence de type S (source) et au moment de la compilation de référence de type T (cible), un casting de conversion existe de S à T si pas d'erreurs de compilation se produire en raison des règles suivantes. Si T est un type d'interface:

Si S n'est pas une classe finale (§8.1.1), puis, s'il existe un supertype X de T, et un supertype Y de S tels que X et Y sont sensiblement distinctes type paramétré, et que les ratures de X et Y sont les mêmes, une erreur de compilation se produit.

Sinon, le casting est toujours légale au moment de la compilation (parce que même si S ne pas mettre en œuvre T, une sous-classe de la S pourrait).

Si S est une classe finale (§8.1.1), alors S doivent mettre en œuvre T, ou une erreur de compilation se produit.

25voto

Etienne Miret Points 2790

C'est parce que la classe Integer est finale et C1 ne l'est pas. Ainsi, un objet Integer ne peut pas implémenter I2, alors qu'un objet C1 pourrait le faire s'il s'agit d'une instance d'une sous-classe de C1 qui implémente I2.

15voto

Buhake Sindi Points 38654

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, une Integer et I2 sont sans rapport avec une quelconque façon, si une erreur de compilation se produit. Aussi, parce qu' Integer est final, il n'y a pas de relation entre Integer et I2.

I2 et I1 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:

  • Si S n'est pas une classe finale (§8.1.1), puis, s'il existe un supertype X de T, et un supertype Y de S tels que X et Y sont sensiblement distinctes type paramétré, et que les ratures de X et Y sont les mêmes, une erreur de compilation se produit.

S est o1 et T est I2.

Espérons que cette aide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X