Java 8 interface/class loader changes?

2019-05-06 21:10发布

问题:

I have found some difficult cautious between Java 1.7_51 and Java 1.8_20.

The initial situation:

One Interface:

interface InterfaceA {
    public void doSomething();
}

Two classes:

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();
    }
}

Next i have compiled the classes with (Java 1.8) -> javac *.java after the compiler finished i removed the InterfaceA.java and InterfaceA.class file's. Now i try again too compile only the ClassB.java and got the error message:

ClassB.java:4: error: cannot access InterfaceA a.doSomething();
class file for InterfaceA not found 1 error

The same i have tried with java 1.7.. -> javac *.java after the compiler finished i removed the InterfaceA.java and InterfaceA.class file's. But know i got no error message ..

Can someone explain me this?

.. sorry for my bad english ..

回答1:

The formal specification describes the process of finding the target method of an invocation expression as first searching all applicable methods and then selecting the most specific one, succeeding if there is no ambiguity.

Compare JLS 15.12.2.1. Identify Potentially Applicable Methods

The class or interface determined by compile-time step 1 (§15.12.1) is searched for all member methods that are potentially applicable to this method invocation; members inherited from superclasses and superinterfaces are included in this search.

In your case it is possible to deduce that the method found in ClassA is an exact match for which the compiler can’t find a more specific method in InterfaceA, however, the specification does not mandate that the compiler has to stop at this point, short-circuiting the search. That’s an optimization a compiler might have, but implementing the search just like formally specified, i.e. searching the entire type hierarchy first and choosing then, is appropriate.

Given how subtle and complex the process is with all the new Java 8 features and type inference, it is understandable that the current implementation is more conservative rather that optimized.



回答2:

I can think of two possible explanations:

  1. Maybe the addition of default methods, or type annotations, or something else to Java 8 meant that the compiler needed to be changed to load the classfiles for indirectly referenced interfaces.

  2. Maybe it was just an harmless side-effect of some other restructuring of the compiler.

Either way, it doesn't necessarily make any difference to what happens at runtime. And the "fix" at compile time is to not remove the interface classfile like that.