为什么向下转换会在这种情况下抛出 ClassCastException?
Why downcasting throws ClassCastException in this case?
我有 2 个包:controller 和 federation。 Controller 只包含 controller class 和 main 方法,但是 federation 包含 2 classes,Shuttle (parent class) 和 MiniShuttle (child class)。向上转型很有魅力,但当我尝试向下转型时,我得到 ClassCastException。
这是我试过的代码:
Shuttle.java
package federation;
public class Shuttle {
protected int passengers;
}
迷你Shuttle.java
package federation;
public class MiniShuttle extends Shuttle {
}
Controller.java
package controller;
import federation.MiniShuttle;
import federation.Shuttle;
public class Controller {
public static void main(String[] args) {
Shuttle shuttle = new Shuttle();
MiniShuttle mshuttle = (MiniShuttle)shuttle;
if(mshuttle instanceof Shuttle)
{
System.out.println("ok");
}else
{
System.out.println("not ok");
}
}
}
因为你实例化了Shuttle
。声明 new Shuttle()
表示类型 Shuttle
的对象被实例化,并且对该对象的引用是 Shuttle
(来自 Shuttle shuttle = ...
)。
如果你想让它工作,使用 Shuttle shuttle = new MiniShuttle()
。有了这个,你实际上是在说 "I'm instantiating an object of MiniShuttle
type and upcasting a reference to it to the type of Shuttle
".
OOPS 中的契约是由 Super classes 而不是 sub classes 定义的。
基本上,扩展合同被定义为 "is a" 关系,其中 subclass 是 Super class 的对象,反之亦然
这样读,MiniShuttle是Shuttle,Shuttle不是MiniShuttle
正如您所说,您正在 downcasting,意思是从父对象到子对象的转换 - 它不会那样工作,因为 shuttle
是类型 Shuttle
而不是 MiniShuttle
。
不过你也可以换个方式:
MiniShuttle miniShuttle = new MiniShuttle();
Shuttle shuttle = (Shuttle) miniShuttle;
这样你就可以向上施法了,这很好,因为每个MiniShuttle
也是Shuttle
。
您在 main 方法的第 1 行中将 "shuttle" 实例化为通用 Shuttle 对象,但随后您试图将其转换为 MiniShuttle。你不能那样做,因为 Shuttle 不一定是 MiniShuttle,而是其他东西。这是另一个示例,希望可以更清楚地说明为什么这是一个错误的假设。更具体的示例说明了为什么这是一个错误的假设。
Shuttle ssQuark = new FerengiShuttle(); // a FerengiShuttle is also a Shuttle
MiniShuttle mshuttle = (MiniShuttle) ssQuark; // No!
FerengiShuttle 是一种穿梭机,mshuttle 也是一种穿梭机,但 ssQuark 不是 MiniShuttle,也从未打算成为。如果您有一个通用的 Shuttle 对象,则无法做出向下转型所需的必要假设。
我有 2 个包:controller 和 federation。 Controller 只包含 controller class 和 main 方法,但是 federation 包含 2 classes,Shuttle (parent class) 和 MiniShuttle (child class)。向上转型很有魅力,但当我尝试向下转型时,我得到 ClassCastException。
这是我试过的代码:
Shuttle.java
package federation;
public class Shuttle {
protected int passengers;
}
迷你Shuttle.java
package federation;
public class MiniShuttle extends Shuttle {
}
Controller.java
package controller;
import federation.MiniShuttle;
import federation.Shuttle;
public class Controller {
public static void main(String[] args) {
Shuttle shuttle = new Shuttle();
MiniShuttle mshuttle = (MiniShuttle)shuttle;
if(mshuttle instanceof Shuttle)
{
System.out.println("ok");
}else
{
System.out.println("not ok");
}
}
}
因为你实例化了Shuttle
。声明 new Shuttle()
表示类型 Shuttle
的对象被实例化,并且对该对象的引用是 Shuttle
(来自 Shuttle shuttle = ...
)。
如果你想让它工作,使用 Shuttle shuttle = new MiniShuttle()
。有了这个,你实际上是在说 "I'm instantiating an object of MiniShuttle
type and upcasting a reference to it to the type of Shuttle
".
OOPS 中的契约是由 Super classes 而不是 sub classes 定义的。 基本上,扩展合同被定义为 "is a" 关系,其中 subclass 是 Super class 的对象,反之亦然
这样读,MiniShuttle是Shuttle,Shuttle不是MiniShuttle
正如您所说,您正在 downcasting,意思是从父对象到子对象的转换 - 它不会那样工作,因为 shuttle
是类型 Shuttle
而不是 MiniShuttle
。
不过你也可以换个方式:
MiniShuttle miniShuttle = new MiniShuttle();
Shuttle shuttle = (Shuttle) miniShuttle;
这样你就可以向上施法了,这很好,因为每个MiniShuttle
也是Shuttle
。
您在 main 方法的第 1 行中将 "shuttle" 实例化为通用 Shuttle 对象,但随后您试图将其转换为 MiniShuttle。你不能那样做,因为 Shuttle 不一定是 MiniShuttle,而是其他东西。这是另一个示例,希望可以更清楚地说明为什么这是一个错误的假设。更具体的示例说明了为什么这是一个错误的假设。
Shuttle ssQuark = new FerengiShuttle(); // a FerengiShuttle is also a Shuttle
MiniShuttle mshuttle = (MiniShuttle) ssQuark; // No!
FerengiShuttle 是一种穿梭机,mshuttle 也是一种穿梭机,但 ssQuark 不是 MiniShuttle,也从未打算成为。如果您有一个通用的 Shuttle 对象,则无法做出向下转型所需的必要假设。