类强制转换异常java

mri*_*ka3 3 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;
        }
}
Run Code Online (Sandbox Code Playgroud)

输出java.lang.ClassCastException.请问xplain为什么会这样?

Dar*_*rov 10

发生这种情况是因为Main是Beta的子类.因此,如果您有Beta(x变量)的实例,则无法将其强制转换为Main.您可以反过来进行转换:如果您有Main实例,则可以将其转换为Beta,因为Main包含Beta的所有方法.


Erw*_*lec 7

稍作修改,您的代码就可以运行:

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
        }
}
Run Code Online (Sandbox Code Playgroud)

但是这个使代码工作的改变显然不足以彻底理解为什么原始代码不起作用,所以我将尝试解释一点继承逻辑和在java中使用强制转换:

首先,您的代码可以使用以下继承/实现"图"来描述:

Foo
 ^
 | (implements)
Beta
 ^
 |  extends
Main

鉴于这些关系,以下陈述是正确的:

  • 可以将Beta的实例分配给(接口)类型Foo的变量

  • 可以将Main的实例分配给(类)类型Beta的变量或(接口)类型Foo的变量

而且......就是这样.所以以下声明是不正确的:

  • 可以将Beta的实例分配给(类)类型Main的变量

仅仅因为类Beta不知道Main类的存在,因为Beta在继承层次中是上层的:这是OO编程中的一般继承契约.

因此你 ClassCastException.

尝试使用instanceof运算符和boolean isAssignableFrom(Class<?> cls)类实例方法(类似这样:)

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

  }
}
Run Code Online (Sandbox Code Playgroud)

所以,为什么你需要使用你必须施放的演员?只有当您知道特定的超类型变量包含特定子类型的实例时.让我们在主要方法中添加几行代码来说明这一点:

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 ;) ?
Run Code Online (Sandbox Code Playgroud)

通常更好 - 恕我直言 - 设计你的程序,以便你最少减少投射(并始终检查instanceofisAssignableFrom()在此之前检查).