我发现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文件。 但是知道我没有错误信息..
有人可以解释一下吗?
..抱歉我的英语不好..
答案 0 :(得分:5)
正式规范描述了查找调用表达式的目标方法的过程,首先搜索所有适用的方法,然后选择最具体的方法,如果没有歧义,则成功。
比较JLS 15.12.2.1. Identify Potentially Applicable Methods
搜索由编译时步骤1(第15.12.1节)确定的类或接口,以查找可能适用于此方法调用的所有成员方法;从超类和超接口继承的成员包含在此搜索中。
在您的情况下,可以推断ClassA
中找到的方法是完全匹配的,编译器无法在InterfaceA
中找到更具体的方法,但是,规范没有要求编译器必须在此时停止,使搜索短路。这是编译器可能具有的优化,但实现搜索就像正式指定一样,即首先搜索整个类型层次结构然后选择,这是合适的。
鉴于所有新的Java 8特性和类型推断过程是多么微妙和复杂,可以理解当前的实现更加保守而非优化。
答案 1 :(得分:3)
我可以想到两种可能的解释:
可能在Java 8中添加默认方法或类型注释或其他内容意味着需要更改编译器以加载间接引用接口的类文件。
也许这只是编译器其他一些重组的无害副作用。
无论哪种方式,它都不一定会对运行时发生的事情产生任何影响。编译时的“修复”是不删除那样的接口类文件。