为什么我们可以将Java接口转换为*任何*非final类?

为什么我们可以将Java接口转换为*任何*非final类?,java,interface,downcast,Java,Interface,Downcast,在上面的代码示例中,我将集合对象强制转换为测试对象。(忽略空指针)。测试和集合并没有任何关系,但这个程序将通过所有编译时检查 我想知道为什么会这样。我的假设是,接口被忽略,因为它们太复杂了。它们没有通用的超类型,每个类都可以实现几个接口,因此类/接口层次结构太复杂,无法有效搜索 除此之外,我还被难倒了。有人知道吗 “非最终”是这里的一个关键词。你可以再上一节课 import java.util.Collection; public class Test { public static

在上面的代码示例中,我将集合对象强制转换为测试对象。(忽略空指针)。测试和集合并没有任何关系,但这个程序将通过所有编译时检查

我想知道为什么会这样。我的假设是,接口被忽略,因为它们太复杂了。它们没有通用的超类型,每个类都可以实现几个接口,因此类/接口层次结构太复杂,无法有效搜索

除此之外,我还被难倒了。有人知道吗

“非最终”是这里的一个关键词。你可以再上一节课

import java.util.Collection;


public class Test
{
    public static void main(String[] args)
    {
        Collection c = null;
        Test s = null;

        s = (Test) c;
    }
}

其实例最终将被分配到
s
使强制转换完全合法。

因为
Test
的子类也可能是
集合的子类型!语言规范设计得有点灵活,允许在运行时验证强制转换。

我们可以从另一个角度来看它:任何非最终类都可以强制转换到任何接口

public class Test2 extends Test implements Collection

啊,我明白了。如果没有测试实现的集合的子类,我仍然希望向下转换失败(类似于如果找不到类型,则在严格的仅类层次结构中转换失败)。这是因为它不值得付出努力吗?编译器不能对类子类做出任何假设。除非该类被标记为
final
,否则您可以使用其类文件对其进行子类化。换句话说,仅仅因为在编译时没有子类,并不意味着在运行时就没有子类。不,这是因为除非测试是final,否则无法知道测试集合中没有子类实现。您的示例非常简单,但在现实生活中,我可以通过网络加载扩展类/通过AOP代理注入扩展类/您对此有何解释
import java.util.function.Predicate;

public class Test {
    public static void main(String[] args) {
        Predicate check;

        try {
            /*It's ok to cast to ANY interface because the Base class is not final.
              Java compiler allows it because some class may extend it 
              and implement the predicate interface. 
              So java compiler can check it only at runtime time not compile time.             
            */
            check = (Predicate)(new Base());

            /*
             Java compiler doesn’t allow it because the BaseFinal is final.
             And it means that no one can extend it and implement interface Predicate. 
             So java compiler can check it at compile time.
            */
            //check = (Predicate)(new BaseFinal()); 
        } catch (ClassCastException e) {
            System.out.println("Class Cast Exception");
        }
        check = (Predicate)(Base)(new Child());
    }    
}
final class BaseFinal {};

class Base {}

class Child extends Base implements Predicate {
    public boolean test(Object t) { return true; }
}