Can someone please explain to me how the compiler does not complain in the first casting, but does complain in the second?
interface I1 { }
interface I2 { }
class C1 implements I1 { }
class C2 implements I2 { }
public class Test{
public static void main(String[] args){
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 !!
}
}
Casting to an interface allows you to pass/refer to objects with the same behavior. For example, if you wanted to make a report from a bunch of forecasts you could write code like this: /* Collect some forecastable things */ List<Forecastable> forecastables = Arrays.
If you have a concrete class, you can cast it to the interface. If you have an interface, it is possible to cast to the concrete class.
There can be only abstract methods in the Java interface, not the method body. It is used to achieve abstraction and multiple inheritance in Java. In other words, you can say that interfaces can have abstract methods and variables. It cannot have a method body.
An interface is a reference type in Java. It is similar to class. It is a collection of abstract methods. A class implements an interface, thereby inheriting the abstract methods of the interface.
When you cast o1
and o3
with (I2)
, you tell the compiler that the class of the object is actually a subclass of its declared type, and that this subclass implements I2
.
The Integer
class is final, so o3
cannot be an instance of a subclass of Integer
: the compiler knows that you're lying. C1
however is not final, so o1
could be an instance of a subtype of C1
that implements I2
.
If you make C1
final, the compiler will complain too:
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 } }
According to JLS chapter 5
Given a compile-time reference type S (source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules. If T is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With