为什么向下转换会在这种情况下抛出 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 对象,则无法做出向下转型所需的必要假设。