Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java how import order matters when import class/enum inner an inner class

Here is my class:

package pepelu;

import pepelu.ImportTest.InnerClass.InnerEnum;
import javax.annotation.Resource;

public class ImportTest {
    @Resource
    public static class InnerClass {
        public enum InnerEnum {
            A
        }
    }

    public static void main(String[] args) {
        System.out.println(InnerEnum.A);
    }
}

When I use maven to build, it will give a compilation error:

mvn clean compile

[ERROR] /Users/finup/Desktop/a/importtest/src/main/java/pepelu/ImportTest.java:[8,6] cannot find symbol

After changing the import order to:

import javax.annotation.Resource;
import pepelu.ImportTest.InnerClass.InnerEnum;

I got a successful maven build.

I searched for documents, but cannot find an explain for this.

Could anyone please explain how import works in this case?

like image 868
Pepe Lu Avatar asked Aug 16 '18 09:08

Pepe Lu


1 Answers

I guess the reason is a "circular" dependency: you have some element X that you import within the same file/class where you are defining it.

Meaning:

import pepelu.ImportTest.InnerClass.InnerEnum;

actually refers to code following in the very same file:

public static class InnerClass {
    public enum InnerEnum {

This means: for the compiler, in order to process that import, it has to look into the body of the class in the same file.

It seems that javac does that "immediately". Meaning: it starts reading import statements, and importing from the same class makes it "suspend" looking at imports, but checking out the following class definition.

And guess what: that class definition makes use of another import. In order to "process" the definition of that enum, the compiler needs to understand where/what that @Resource annotation is about. But it doesn't know the annotation yet (because the compiler didn't see the import, yet).

When you change the order, the compiler understands that @Resource usage in the class definition.

And of course: the real answer is not to reorder imports. The real answer is to not import something from the class that is following after the import statements. There is absolutely no point in doing so.

Edit, given the comment by the OP about how this can work in Redisson: honestly, I don't know. It might depend on how exactly that class is compiled. Maybe such code works with newer (or older) versions of javac, maybe this works with specific versions of the eclipse or intellij or xyz compiler.

Meaning: I gave you an explanation why you are running into this problem. That doesn't mean that any compiler must necessarily run into the same problem.

like image 101
GhostCat Avatar answered Sep 21 '22 12:09

GhostCat