类强制转换异常java
输出类强制转换异常java,java,Java,输出java.lang.ClassCastException。 为什么会这样,请解释一下?之所以会这样,是因为Main是Beta的一个子类。因此,如果您有Beta的实例(变量x),则无法将其强制转换为Main。您可以用另一种方式进行强制转换:如果您有一个Main实例,您可以将其强制转换为Beta,因为Main包含Beta的所有方法。因为您无法将Beta强制转换为Main。 您不能将基类强制转换为派生类。正如Darin所说,您不能将超类的对象强制转换为子类。我想你真正想做的是:Foo f=x(因为
java.lang.ClassCastException
。
为什么会这样,请解释一下?之所以会这样,是因为Main是Beta的一个子类。因此,如果您有Beta的实例(变量
x
),则无法将其强制转换为Main。您可以用另一种方式进行强制转换:如果您有一个Main实例,您可以将其强制转换为Beta,因为Main包含Beta的所有方法。因为您无法将Beta强制转换为Main。
您不能将基类强制转换为派生类。正如Darin所说,您不能将超类的对象强制转换为子类。我想你真正想做的是:
Foo f=x代码>(因为Beta实现了Foo,所以根本不需要强制转换)。与其他人所说的不同,从一个类强制转换到它自己的子类是正确的。事实上,这是Java中唯一有效和有用的强制转换用例。
强制转换(T)e
在运行时检查将对象视为某种类型的对象是否有效。在您的程序中,这是无效的,因为x
指的是Beta
类型的对象,它不是Main
类型
所以这完全是预期的行为。您不能将基类强制转换为派生类。如果要使用Main类类型创建Foo实例,可以使用如下方法:
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;
}
}
只需稍作更改,您的代码即可工作:
interface Foo { }
class Beta implements Foo { }
public class Main extends Beta {
public static void main (String[] args) {
Foo x = new Main();
}
}
但是,为了使代码正常工作而进行的这一更改显然不足以彻底理解原始代码为什么不能正常工作,因此我将尝试解释一些继承逻辑和java中强制转换的使用:
首先,您的代码可以用以下继承/实现“图”来描述:
那么,你为什么要使用cast呢?你必须使用cast吗?只有当您知道特定的超类型变量包含特定子类型的实例时。让我们在主要方法中再添加几行来说明这一点:
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
}
}
通常,更好的做法是(IMHO)设计程序,使您的强制转换最小化(并且在执行此操作之前,始终检查instanceof
或isAssignableFrom()
)。仅当要强制转换的对象实际上是该子类上的实例时,才可以将对象强制转换为子类
所以如果你有这样的东西:
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 ;) ?
然后,上述转换将起作用,因为“new Main()”将为您提供一个Main实例。请查看代码和发布格式指南。使用编辑字段下方的预览来控制正在执行的操作。祝你玩得愉快。:)不需要。Main
已经是Beta
了,根本不需要铸造。类似地,Beta x
已经是Foo
了,也不需要强制转换。@用户未知虽然Main
已经是Beta
,但是创建的是一个新的Beta
(而不是Main
),你不能放弃。是的,但你监督,你永远不会放弃<代码>Foo f=x代码>不需要强制转换,因为每个测试版都实现了Foo。您不会将Main强制转换为Beta版,因为每个Main都已经是Beta版。@用户未知:这一步没有优化。首先将x
转换为Beta
,然后才进行分配。而且铸造步骤无法完成。该转换实际上是一个涉及类型检查的运行时操作,而不仅仅是对编译器的提示。到目前为止我还没有看到演员。在Main的下一行中尝试一个铸造,该铸造将失败,因为x从来都不是Main。对f的赋值(声明为Foo)也不需要强制转换。我不知道mrig试图通过sidestep到(Main)x实现什么,但您几乎不需要将Main转换为Beta,因为它始终是Beta。Thomas在他对Overbose的评论中发现了一个例子,当时他试图调用一个重载方法。子类已经是超类类型,根本不需要强制转换。对象o=新字符串(“不涉及铸造”);事实上,你只能反过来,但您不能将每个对象强制转换为字符串,而只能将碰巧是字符串的对象强制转换为字符串。@用户未知:在某些情况下,如果要显式使用已在子类中重写的基类的方法,则应将子类强制转换为超类类型。@user未知假定您有方法foo(Bar b)
和foo(Baz b)
使用类栏扩展Baz
,您可能需要调用foo((Baz)栏)代码>以便调用第二个方法而不是第一个方法。-我承认Overbose的说法有点错误:您不能重写方法并更改参数类型。这不是重写,而是重载。@Thomas@user unknown:是的。我的意思是重载,因为Darin是假的,你也是。当然,您可以将超类强制转换为子类;你不能将一个超类强制转换成每个子类。引用必须指向该特定子类的类型。@用户未知如果引用的对象已经是该类型的子类,并且引用本身是一个超类,则可以强制转换。但不能将超类的对象强制转换为子类。我们讨论的不是一般的强制转换,而是将Beta
对象强制转换为Main
(注意,实际上对象是Beta
,而不仅仅是对它的引用)。引用就是引用。如果引用的只是对超类对象的引用,则不能将其强制转换为派生类(但可以尝试)。但铸造方向始终是从超类型到派生类型。另一方面,每个Main都是Beta版,不需要强制转换。@简而言之,user unknown:您不能将一个类的对象强制转换为该类的子类。在这里,对引用所做的任何操作都无关紧要,因为检查总是在对象上进行的。我相应地更新了答案。关于引用的强制转换,你是对的。然而,我们所做的
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
}
}
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 ;) ?
Beta x = new Main();