Java 缩小引用从类型到接口(interface)的转换

标签 java casting type-narrowing

尝试理解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) TS 子类的实例分配给 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
{
}

让我们解释一下这种转换的两个条件:

  1. “C 不是最终的” - 如果它是 final,则不会有 C 的子类,因此编译器肯定知道此转换永远无法工作,并且编译失败。

  2. “不实现 K” - 如果 C 实现 K,则这不再是缩小转换。它变成了Widening Reference Conversion ,保证在运行时成功。事实上,没有必要使用强制转换运算符。一个简单的作业就可以了。

关于Java 缩小引用从类型到接口(interface)的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54199861/

相关文章:

java - 模拟或模拟消息队列 (JMS)

java - ArrayList for 循环最有效的实现是什么?

typescript - 控制流不使用联合元组进行类型缩小?

c++ - 为什么初始化列表允许在 C++ 中缩小类型?

传递给函数时对象中键的 typescript 缩小

java - 混淆代码时如何使用proguard-maven-plugin过滤所有maven依赖?

java - 在 ArrayList 中搜索字符串;总是返回 false

c++ - 如何在不制作拷贝的情况下将 `std::string` 转换为 `std::vector<unsigned char>`?

.net - Oracle NUMBER 问题 : Decimal to Int64 cast

java - JAVA如何改变数据类型而不改变变量名