【问题标题】:Java Compiler and Interface castingJava 编译器和接口转换
【发布时间】:2016-02-18 18:27:41
【问题描述】:

我正在研究 Java 中的强制转换,特别是使用接口进行强制转换。假设我有一个接口I,它定义了一个方法跳转,即:

interface I{
    public void jump();
}

另外假设我还有 3 个其他类,ABCA 实现 IB 没有。但是,C 扩展了B 并实现了I

class A implements I {
   public void jump(){
      System.out.print("A is jumping");
   }
}
class B { } 
class C extends B implements I {
    public void jump(){
        System.out.print("C is jumping");
    }
}

现在,如果我尝试将A 类型的对象分配给I,没有问题,我什至不需要演员表。即:

I i = new A();

没问题,不需要强制转换。

大概这是因为编译器知道 A 实现了 I。此外,如果我尝试这样做:

A mya = new A();
I i = mya;

没有问题,即使mya 可能引用A 的子类。但是 AFAIK 没关系,因为编译器知道 A 的每个子类都必须隐式实现 jump 方法,因此接口 A

但是,如果我尝试将B 类型的对象分配给I,那么我确实需要一个演员表。例如

B myb = new B();
I i = (I)myb;

大概这是因为编译器知道B 没有实现I。然而,由于B 可以引用实现I 的子类,因此您可以转换为I。到现在为止还挺好。 现在这是我的问题:如果我想将引用C(实现I)类型的对象的B 类型的对象分配给I,那么我们需要一个演员表。这是为什么?例如。

B b = new C();
I myI = b; //Won't compile this needs a cast
I myI = (C)b; // This will compile
myI = (I)b; // This will also compile

为什么编译器不明白 B 指的是实现 I 的 C

大概是因为B 可以引用B,它实际上并没有实现I,但是为什么编译器不知道呢?大概编译器仅限于每行可用的信息?它无法运行您的程序并看到b 实际上指向C?如果这是正确的,有人可以指出一些关于 Java 编译器如何工作以及它们的局限性的文献的方向吗?

【问题讨论】:

    标签: java interface casting


    【解决方案1】:

    这大概是因为编译器知道 B 没有实现 I,但是由于 B 可以引用一个确实实现了 I 的子类,所以你可以强制转换为 I。

    不完全是。编译器将允许您随意转换 B。这并不意味着您不会在运行时获得ClassCastException。 (这次你的代码可以工作,但编译器不会阻止你做出错误的强制转换。)

    为什么编译器不理解 B 指的是实现 I 的 C?大概是因为 B 可以引用实际上没有实现 I 的 B 但为什么编译器不知道这一点。

    因为您在声明 B b = new C(); 时告诉它将该对象视为 B

    大概编译器仅限于仅在每一行上可用的信息?它无法通过你的程序运行并看到 b 实际上指向 a c?

    它可以访问其余代码。它只是按照你告诉它的去做:将b 视为B 类的对象。

    【讨论】:

    • 加一个表示“告诉它治疗”
    【解决方案2】:

    在这种特殊情况下,编译器有能力确定 b 实际上是指 C 的一个对象。但是语言创建者选择不让编译器如此智能。

    在实际场景中,b 所指的实际对象不会如此本地化,因此编译时间无法确定。所以选择不要让编译器过于智能,这不能解决实际场景。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-13
      • 1970-01-01
      • 2018-11-15
      相关资源
      最近更新 更多