Reputation: 687
interface Foo {
}
class Beta implements Foo {
}
public class Main extends Beta{
public static void main(String[] args) {
Beta x = new Beta();
Foo f= (Main)x;
}
}
output java.lang.ClassCastException
.
Why it is happening please xplain?
Upvotes: 3
Views: 9308
Reputation: 229
You can Cast an object to a subclass only if the object being casted is actually an instance on this subclass.
So if you have something like this:
Beta x = new Main();
then the above casting will work, since "new Main()" will give you an instance of Main.
Upvotes: 0
Reputation: 726
With a slight change, your code would work :
interface Foo {
}
class Beta implements Foo {
}
public class Main extends Beta{
public static void main(String[] args) {
Beta x = new Beta();
Foo f = x; // Cast to main removed --> works
}
}
But this change to make the code work is obviously not enough to get a thorough understanding of why the original code doesn't work, so I'll try and explain a bit inheritance logic and the use of casts in java :
First, your code can be described with the following inheritance/implementation "diagram" :
Foo ^ | (implements) Beta ^ | extends Main
Given these relationships, the following statements are correct :
An instance of Beta can be assigned to a variable of (interface) type Foo
An instance of Main can be assigned to a variable of (class) type Beta or a variable of (interface) type Foo
And... That's about it. So the following statement is incorrect :
Simply because class Beta has no knowledge of the existence of class Main, as Beta is upper in the inheritance hierachy : this is the general inheritance contract in OO programming.
Hence you ClassCastException.
Try playing with the instanceof
operator and the boolean isAssignableFrom(Class<?> cls)
Class instance method (something like this :)
interface Foo {
}
class Beta implements Foo {
}
public class Main extends Beta {
public static void main(String[] args) {
// Let's create some instances of Main and Beta :
Beta b = new Beta();
Main m = new Main();
// Let's test those newly created instances :
System.out.println("is m an instance of Foo ? : " + (m instanceof Foo)); // output true
System.out.println("is b an instance of Foo ? : " + (b instanceof Foo)); // output true
System.out.println("is m an instance of Beta ? : " + (m instanceof Beta)); // output true
System.out.println("is b an instance of Beta ? : " + (b instanceof Beta)); // output true (obviously !)
System.out.println("is m an instance of Main ? : " + (m instanceof Main)); // output true (obviously !)
System.out.println("is b an instance of Main ? : " + (b instanceof Main)); // output FALSE !
// Explanations with the isAssignableFrom() method :
// Obvious !
System.out.println("is a variable of type Foo assignable a from a Foo instance ? : "
+ Foo.class.isAssignableFrom(Foo.class)); // output true
System.out.println("is a variable of type Main assignable from a Main instance ? : "
+ Main.class.isAssignableFrom(Main.class)); // output true
System.out.println("is a variable of type Beta assignable from a Beta instance ? : "
+ Beta.class.isAssignableFrom(Beta.class)); // output true
// Now the real thing :
System.out.println("is a variable of type Foo assignable from a Beta instance ? : "
+ Foo.class.isAssignableFrom(Beta.class)); // output true
System.out.println("is a variable of type Foo assignable from a Main instance ? : "
+ Foo.class.isAssignableFrom(Main.class)); // output true
System.out.println("is Main assignable from Beta ? : " + Main.class.isAssignableFrom(Beta.class)); // output false
System.out.println("is Main assignable from Foo ? : " + Main.class.isAssignableFrom(Foo.class)); // output false
System.out.println("is Beta assignable from Main ? : " + Beta.class.isAssignableFrom(Main.class)); // output true
System.out.println("is Beta assignable from Foo ? : " + Beta.class.isAssignableFrom(Foo.class)); // output false
// Thus the following will work (for example):
// direct assignation to interface variables (NO CAST is necessary) :
Foo fb = b;
Foo fm = m;
// Some tests :
System.out.println("is fm an instance of Main ? : " + (fb instanceof Main)); // output true
System.out.println("is fb an instance of Beta ? : " + (b instanceof Beta)); // output true
// getting up the hierarchy of main step by step (NO CAST is necessary) :
Beta bm = m;
Foo fbm = bm;
System.out.println("is bm an instance of Main ? : " + (fb instanceof Beta)); // output true
System.out.println("is fbm an instance of Main ? : " + (b instanceof Main)); // output true
}
}
So, Why do you need to use cast you have to cast anyway ? Only when you know a specific supertype variable contains an instance of a specific subtype. Let's add a few more lines these line to our main method to illustrate this :
Object o = m; // m is an instance of Main, but also of java.lang.Object
Foo f2 = (Foo)o; // wont'compile without casting !
Beta b2 = (Beta)o; // wont'compile without casting !
Main m2 = (Main)o;
//And... finally :
Beta b3 = m;
Main m3 = (Main)b3; // won't compile without casting !
// Got it ;) ?
It is often better - IMHO - to design your program so that your reduce casting at minimum (and always check with instanceof
or isAssignableFrom()
before doing so).
Upvotes: 7
Reputation: 88707
As Darin already said, you can't cast objects of a superclass to a subclass. I think what you really want to do is this: Foo f= x;
(since Beta implements Foo no cast is necessary at all).
Upvotes: 0
Reputation: 505
You cannot cast base class to derived class. If you want to make Foo instance with Main class type, you can use like below:
interface Foo { }
class Beta implements Foo { }
public class Main extends Beta {
public static void main (String[] args) {
Foo x = new Main();
}
}
Upvotes: 0
Reputation: 7404
In contrast to what others have said, it is correct to cast from a class to own of its sub classes. In fact that is the only valid and useful use case of casts in Java.
A cast (T)e
checks at runtime whether it is valid to a treat an object as an object of some type T
. And in your program this is not valid, because x
refers to an object of type Beta
which is not of type Main
.
So this is totally expected behavior.
Upvotes: 1
Reputation: 39164
Because you can't cast Beta to Main. You can't cast a base class to a derived one.
Upvotes: 0
Reputation: 1038710
This happens because Main is a subclass of Beta. So if you have an instance of Beta (the x
variable) you cannot cast it to Main. You can do the casting the other way round: if you have an instance of Main you can cast it to Beta because Main contains all the methods of Beta.
Upvotes: 10