mriganka3
mriganka3

Reputation: 687

class cast exception java

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

Answers (7)

Vibhor
Vibhor

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

Erwan Queffélec
Erwan Queffélec

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 :

  • An instance of Beta can be assigned to of variable of (class) type Main

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

Thomas
Thomas

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

dbyuvaraj
dbyuvaraj

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

jmg
jmg

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

Heisenbug
Heisenbug

Reputation: 39164

Because you can't cast Beta to Main. You can't cast a base class to a derived one.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

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

Related Questions