Why the following is possible in Java ?
Integer[] ints = (Integer[])new Comparable[10];
But it gets ClassCastException
at runtime. What is the usecase to new
an array of an interface.
Why the following is possible in Java ?
Integer[] ints = (Integer[])new Comparable[10];
But it gets ClassCastException
at runtime. What is the usecase to new
an array of an interface.
To answer the specific question:
Comparable toComplare[] = new Comparable[10];
Why not create an array that will allow you to store any object that implements the Comparable interface?!
The point is: the interface denotes a "common functionality" - and it could be helpful to only look at objects from that "view".
Of course, the objects stored in that array are always of some "real" class - but all these objects will implement the functionality that the Comparable
interface provides.
So you could do things like:
toCompare[0] = new Integer(5);
toCompare[1] = new BigDecimal("3.2");
...
I am not saying that this is something that you would use frequently, but as said - it allows you to "collect" objects under a certain, specific "view" of their capabilities. It is also worth pointing out: having such an array does not mean that you would be able to do:
toCompare[0].compareTo(toCompare[1]);
successfully!
Beyond that: a cast always implies somehow that you, the programmer know something the compiler doesn't know. So the compiler steps back and lets you do that - assuming you know what you are doing. But as the code you are showing in the question is obviously not correct, reality comes back biting you at runtime. And yes, it would be possible to decide at compile that the given code is incorrect.
Regard this case: You have an interface and two (or more) classes that implement that interface:
interface MyInterface
{
public void someMethod();
}
class MyClass1 implements MyInterface
{
public void someMethod() { System.out.println("foo");}
}
class MyClass2 implements MyInterface
{
public void someMethod() { System.out.println("bar");}
}
And you call it like this:
public static void main(String[] args)
{
MyInterface[] array = new MyInterface[2];
array[0] = new MyClass1();
array[1] = new MyClass2();
array[0].someMethod();
array[1].someMethod();
}
An array of an interface gives you the method of holding different implementations of that interface in an array
Having Integer
implement Comparable
, doesn't mean Integer[]
implements Comparable[]
, so you can't convert arrays of different type. You can, however, put Integer
in element of Comparable[]
array.
The compiler looks at the type of the right side, and sees that it is an array of Comparable
. In general, it could be an Integer[]
(because that is assignable to Comparable[]
).
We know that it will not be an Integer[]
, because that right-hand expression is a constructor call. But the compiler does not look that far. It uses the same logic as if that expression was a method call with a declared type of Comparable[]
. It does not look inside to figure out the actual type.
So the compiler will accept your typecast, because it might succeed. It will only reject casts that cannot work out at all (according to declared types), such as casting Integer
to String
.
Note that it is probably a design flaw to allow this co-variance in arrays. You can cast Integer[]
to Comparable[]
, but this has problems and for this reasons you cannot cast List<Integer>
to List<Comparable>
.
ClassCastException
is due to Heap Pollution.
Find more details here http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ050new
to an interface array / just interface is to fill it with any class object which implements that interface (or) give an anonymous inner class definition.It is because you are performing a Narrowing Reference Conversion
The class Integer implements the Comparable interface:
public final class Integer extends Number implements Comparable<Integer>
see: 5.1.6. Narrowing Reference Conversion
From any array type SC[] to any array type TC[], provided that SC and TC are reference types and there is a narrowing reference conversion from SC to TC.
Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If not, then a ClassCastException is thrown.