简体   繁体   English

class 强制转换异常 java

[英]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 . output java.lang.ClassCastException Why it is happening please xplain?为什么会这样,请解释一下?

This happens because Main is a subclass of Beta.发生这种情况是因为 Main 是 Beta 的子类。 So if you have an instance of Beta (the x variable) you cannot cast it to Main.因此,如果您有一个 Beta 实例( x变量),则不能将其转换为 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.您可以反过来进行转换:如果您有 Main 的一个实例,您可以将其转换为 Beta,因为 Main 包含 Beta 的所有方法。

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:但是这种让代码工作的改变显然不足以彻底理解为什么原始代码不能工作,所以我将尝试解释一下 inheritance 的逻辑和 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可以将Beta的实例分配给(接口)类型为Foo的变量

  • An instance of Main can be assigned to a variable of (class) type Beta or a variable of (interface) type Foo Main的实例可以分配给(类)类型Beta的变量或(接口)类型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可以将Beta的实例分配给(类)类型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. 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.因此你ClassCastException.

Try playing with the instanceof operator and the boolean isAssignableFrom(Class<?> cls) Class instance method (something like this:)尝试使用instanceof运算符和boolean isAssignableFrom(Class<?> cls) Class 实例方法(类似这样:)

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:让我们在 main 方法中再添加几行来说明这一点:

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).通常更好 - 恕我直言 - 设计您的程序,以便您至少减少转换(并且在这样做之前始终检查instanceofisAssignableFrom() )。

In contrast to what others have said, it is correct to cast from a class to own of its sub classes.与其他人所说的相反,从 class 转换为拥有它的子类是正确的。 In fact that is the only valid and useful use case of casts in Java.事实上,这是 Java 中唯一有效且有用的强制转换用例。 A cast (T)e checks at runtime whether it is valid to a treat an object as an object of some type T .强制转换(T)e在运行时检查将 object 视为某种类型T的 object 是否有效。 And in your program this is not valid, because x refers to an object of type Beta which is not of type Main .在您的程序中,这是无效的,因为x指的是Beta类型的 object ,它不是Main类型。

So this is totally expected behavior.所以这是完全预期的行为。

You can Cast an object to a subclass only if the object being casted is actually an instance on this subclass.只有当被强制转换的 object 实际上是该子类上的实例时,您才能将 object 强制转换为子类。

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.那么上面的转换就会起作用,因为“new Main()”会给你一个 Main 的实例。

Because you can't cast Beta to Main.因为您不能将 Beta 转换为 Main。 You can't cast a base class to a derived one.您不能将基础 class 转换为派生的。

As Darin already said, you can't cast objects of a superclass to a subclass.正如 Darin 已经说过的,您不能将超类的对象强制转换为子类。 I think what you really want to do is this: Foo f= x;我认为您真正想做的是: Foo f= x; (since Beta implements Foo no cast is necessary at all). (因为 Beta 实现了 Foo 根本不需要强制转换)。

You cannot cast base class to derived class.您不能将基础 class 转换为派生 class。 If you want to make Foo instance with Main class type, you can use like below:如果你想用Main class 类型制作Foo实例,你可以像下面这样使用:

interface Foo { }
class Beta implements Foo { }

public class Main extends Beta {

    public static void main (String[] args) {
         Foo x = new Main(); 
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM