【问题标题】:Java 8 interface/class loader changes?Java 8 接口/类加载器更改?
【发布时间】:2014-11-07 11:05:53
【问题描述】:

我发现 Java 1.7_51 和 Java 1.8_20 之间有些难以谨慎。

初始情况:

一个接口:

interface InterfaceA {
    public void doSomething();
}

两个类:

public class ClassA implements InterfaceA { 
    public void doSomething() {
        System.out.println("Hello World!");
    }
}

public class ClassB {
    public static void main(String[] args) {
        ClassA a = new ClassA();
        a.doSomething();
    }
}

接下来我用 (Java 1.8) -> javac *.java 编译了这些类 编译器完成后,我删除了 InterfaceA.java 和 InterfaceA.class 文件。 现在我再次尝试只编译 ClassB.java 并收到错误消息:

ClassB.java:4:错误:无法访问 InterfaceA a.doSomething();
未找到 InterfaceA 的类文件 1 个错误

我用 java 1.7 尝试过的相同.. -> javac *.java 编译器完成后,我删除了 InterfaceA.java 和 InterfaceA.class 文件。 但是知道我没有收到错误消息..

谁能解释一下?

..对不起我的英语不好..

【问题讨论】:

  • 通常该类将通过 RMI 重新加载

标签: java compiler-errors java-8 java-7


【解决方案1】:

正式规范将寻找调用表达式的目标方法的过程描述为首先搜索所有适用的方法,然后选择最具体的方法,如果没有歧义则成功。

比较JLS 15.12.2.1. Identify Potentially Applicable Methods

在编译时步骤 1(第 15.12.1 节)确定的类或接口中搜索所有可能适用于此方法调用的成员方法;此搜索包括从超类和超接口继承的成员。

在您的情况下,可以推断出在 ClassA 中找到的方法与编译器在 InterfaceA 中找不到更具体的方法完全匹配,但是,规范并不要求编译器必须在这一点停止,使搜索短路。这是编译器可能有的优化,但是按照正式规定的方式实现搜索,即先搜索整个类型层次结构然后再选择,是合适的。

考虑到所有新的 Java 8 功能和类型推断的过程是多么微妙和复杂,当前的实现更加保守而不是优化是可以理解的。

【讨论】:

    【解决方案2】:

    我能想到两种可能的解释:

    1. 可能在 Java 8 中添加默认方法、类型注释或其他内容意味着需要更改编译器以加载间接引用接口的类文件。

    2. 也许这只是编译器其他一些重组的无害副作用。

    无论哪种方式,它都不一定会对运行时发生的事情产生任何影响。编译时的“修复”是不要像那样删除接口类文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多