尝试理解java从类到接口(interface)的缩小转换。 JLS( JLS-5.1.6 ) 指出:
From any class type C to any non-parameterized interface type K, provided that C is not final and does not implement K.
为了测试这一点,我创建了一个类和一个接口(interface)。然后尝试将类强制转换为接口(interface),但出现运行时 ClassCastException。这是我的代码示例。
class NarrowingReferenceConversion
{
public static void main(String args[])
{
S s = new S();
T t = (T)s;
}
}
interface T
{
public void print();
}
class S
{
public void print(){
System.out.println("S.print()");
}
}
在编译和运行上述内容时,我收到以下错误消息:
Exception in thread "main" java.lang.ClassCastException: S cannot be cast to T
最佳答案
这是一种不能保证有效的转换,就像不能保证将基类的引用强制转换为子类一样。这就是为什么它被视为缩小转换。
编译器知道转换可能在运行时起作用,因此它允许转换,但如果不起作用,则会在运行时抛出 ClassCastException
。
仅当您将实现接口(interface) T
的 S
子类的实例分配给 s
时,转换才会起作用.
class NarrowingReferenceConversion
{
public static void main(String args[])
{
S s = new S2();
T t = (T) s; // this will work, since S2 implements T
}
}
interface T
{
public void print();
}
class S
{
public void print(){
System.out.println("S.print()");
}
}
class S2 extends S implements T
{
}
让我们解释一下这种转换的两个条件:
“C 不是最终的” - 如果它是
final
,则不会有C
的子类,因此编译器肯定知道此转换永远无法工作,并且编译失败。“不实现 K” - 如果
C
实现K
,则这不再是缩小转换。它变成了Widening Reference Conversion ,保证在运行时成功。事实上,没有必要使用强制转换运算符。一个简单的作业就可以了。
关于Java 缩小引用从类型到接口(interface)的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54199861/