Import statement processing

JDK Enhancement Proposal (JEP) 216 was issued as a fix to javac in regard to how import statements are processed. Prior to Java 9, there were instances where the order of import statements would impact if the source code was accepted or not. 

When we develop applications in Java, we typically add import statements as we need them, resulting in an unordered list of import statements. IDEs do a great job of color-coding import statements that are not used, as well as informing us of import statements we need, but that has not been included. It should not matter what order the import statements are in; there is no applicable hierarchy. 

javac compiles classes in two primary steps. Specific to handling import statements, these steps are as follows:

  • Type resolutionThe type resolution consists of a review of the abstract syntax tree to identify declarations of classes and interfaces
  • Member resolution: The member resolution includes determining the class hierarchy and individual class variables and members

Starting with Java 9, the order in which we list import statements in our classes and files will no longer impact the compilation process. Let's look at an example:

package samplePackage;

import static SamplePackage.OuterPackage.Nested.*;
import SamplePackage.Thing.*;

public class OuterPackage {
public static class Nested implements Inner {
// code
}
}

package SamplePackage.Thing;

public interface Inner {
// code
}

In the preceding example, type resolution occurs and results in the following realizations:

  • SamplePackage.OuterPackage exists
  • SamplePackage.OuterPackage.Nested exists
  • SamplePackage.Thing.Innner exists

The next step is member resolution, and this is where the problem existed prior to Java 9. Here is an overview of the sequential steps javac would use to conduct the member resolution for our sample code:

  1. Resolution of SamplePackage.OuterPackage begins.
  2. The SamplePackage.OuterPackage.Nested import is processed.
  3. Resolution of the SamplePackage.Outer.Nested class begins.
  4. The inner interface is type checked, although, because it is not in scope at this point, the inner interface cannot be resolved.
  5. Resolution of SamplePackage.Thing begins. This step includes importing all member types of SamplePackage.Thing into scope.

So, the error occurs, in our example, because Inner is out of scope when resolution is attempted. If steps 4 and 5 were swapped, it would not have been a problem.

The solution to the problem, implemented in Java 9, was to break the member resolution steps into additional substeps. Here are those steps:

  1. Analyze the import statements
  2. Create the hierarchy (class and interfaces)
  3. Analyze class headers and type parameters