Java编译器和接口转换

Java编译器和接口转换,java,interface,casting,Java,Interface,Casting,我正在研究Java中的强制转换,特别是使用接口进行强制转换。假设我有一个定义方法跳转的接口I,即: interface I{ public void jump(); } 另外,假设我还有3个类,A,B和CA实现IB没有。但是,C扩展了B并实现了I class A implements I { public void jump(){ System.out.print("A is jumping"); } } class B { } class C extends

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

interface I{
    public void jump();
}
另外,假设我还有3个类,
A
B
C
<代码>A实现
I
<代码>B没有。但是,
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
的子类。但这没关系,因为编译器知道
A
的每个子类都必须隐式实现
jump
方法,因此接口
A

但是,如果我尝试将
B
类型的对象分配给
I
,那么我确实需要强制转换。e、 g

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
实际上指向a
C
?如果这是正确的,有人能告诉我一些关于Java编译器如何工作以及它们的局限性的文献吗

这大概是因为编译器知道B不实现I,但是因为B可以引用实现I的子类,所以您可以强制转换为I

不完全是。编译器将允许您根据需要强制转换B。这并不意味着您在运行时不会得到
ClassCastException
。(这次代码可以正常工作,但编译器不会阻止您进行错误的强制转换。)

为什么编译器不明白B指的是实现I的C?这大概是因为B可以引用一个B,而B实际上并没有实现I,但为什么编译器不知道呢

因为您在声明
bb=newc()时告诉它将对象视为a
B

大概编译器仅限于每行上可用的信息?它不能在你的程序中运行,并看到b实际上指向c


它可以访问代码的其余部分。它只是在做你告诉它要做的事情:把
b
当作类
b

的对象。在这种特殊情况下,编译器有能力确定b实际上是指C的对象。然而,语言创建者选择了不让编译器这么聪明的方法

在实际场景中,b所指的实际对象不会如此本地化,因此编译时是可确定的。因此,选择它是为了不让编译器过于智能,因为它不能解决实际情况。

加上一个“告诉它处理”