在接口之间进行转换

5

我的问题与Java语言相关。 这是我得到的:

interface I1{}
interface I2{}
class C1 implements I1{}
class C3 extends C1 implements I2{}

当...
     C1 01;
     C3 o3;
     I1 i1;

现在看来,I2 i2 = (I2) i1; 是正确的,因为在运行时,i1实际上指的是实现了I2接口的对象。但我不太理解。接口之间没有关系,那么如何将其强制转换为相邻的接口呢?这里没有更多的代码,只是为了准备Java认证。

最好的问候


在你的代码中,即使接口之间没有直接关系,它们也通过实现它们的类之间存在关系。 - techfoobar
2
i1 变量在哪里声明的? - Sergey Kalinichenko
1
请发布i1变量的声明。完整的代码片段会更加有用。 - Marko Topolnik
@techfoobar 如果您正在尝试将类型为I1的表达式转换为I2,则该关系无关紧要。运行时值类型在这里不起作用。 - Marko Topolnik
4个回答

4

如果你将一个 Integer 强制转换成 String,编译器会认为这是非法的,但是由于一个类可以实现多个接口,编译器无法知道当你将一个接口类型强制转换为另一个接口类型时是否违反了规定。考虑以下代码:

I1 i1 = getI1();
if (i1 instanceof I2) {
  I2 i2 = (I2) i1;
}

如果Java编译器不允许从一个接口转换到另一个接口,那么这段完全合法的代码将无法编译。

3

I2 i2 = (I2) i1;的意思是:我知道由i1引用的对象的具体运行时类型实现了I2接口,因此我想将其作为I2引用。如果i1的具体运行时类型确实实现了I2,则转换将成功。

I1I2没有任何共同点并不重要。重要的是i1引用的对象的实际具体运行时类型。


1
简单来说,接口就像一种类型,就像鸟类-不是老鹰或鸭子。 拿这些类的具体实现(这有点儿傻,但请忍耐)来举例。
interface Bird {fly();}
interface Swimmer {swim();}
class Eagle implements Bird {fly(){...};}
class Duck extends Eagle implements Swimmer {swim(){...};}

Swimmer i2 = (Swimmer) i1;

这意味着您的代码认为i1是一个可以游泳的实体。如果i1是一只鸭子,这段代码将起作用;如果是一只老鹰,它将失败。类型转换是在运行时而不是编译时完成的。


类不仅声明接口,还声明类型。 - André Stannek
真的 - 我试图过于简化(并在答案中加入了一只游泳的鸭子)。这个问题看起来已经被回答了。 - Rajiv

1

你自己回答了这个问题 ;-)

"[... ]is right because at run time i1 actually refers to an object that implements I2"

类型转换是在运行时而不是编译时进行评估的。因此,如果 i1 在运行时指向的对象是 I2 类型,则不会出现错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接