Java import static fails when imported class extends 3rd party lib
Asked Answered
T

1

6

The problem setup consists of three java libs (I stripped all package names for readability, full qualified names are used everywhere):

  1. external-lib: provides the abstract class

    public abstract class AbstractExternal {}
    
  2. my-lib-A: provides the class

    public class ClassA extends AbstractExternal {
        public static final String FOO = "foo";
    }
    

    external-lib is in my-lib-A's classpath.

  3. my-lib-B statically imports FOO from ClassA:

    import static ClassA.FOO;
    public class ClassB {
        private String foo = FOO;
    }
    

    my-lib-A is in my-lib-B's classpath but external-lib is not.

Problem: The import static line produces the following error:

The type AbstractExternal cannot be resolved. It is indirectly referenced from required .class files.

However (1), when modifying ClassB to

import ClassA;
public class ClassB {
    private String foo = ClassA.FOO;
}

the compiler is happy.

However (2), when adding a second abstraction two my-lib-A like

public class AbstractClassA extends AbstractExternal {}

and

public class ClassA extends AbstractClassA {
    public static final String FOO = "foo";
}

the static import of ClassA.FOO in the example above works.

Question 1: Why does import static ClassA.FOO fails while import ClassA with ClassA.FOO works?

Question 2: Why does import static ClassA.FOO works when it extends another class from my-lib-A which then extends AbstractExternal?

Edit: a significant information: the compiler in question is the Eclipse Compiler for Java (ECJ).

Edit 2: javac is in sync with ECJ and is able to compile the normal import and class access in ClassB while the static import fails.

Twostep answered 16/4, 2018 at 14:17 Comment(0)
M
2

Ecj ideally "shouldn't" report this error. I filed Bug 533890 to track this.

The common theme behind all errors of this message ("... cannot be resolved. It is indirectly referenced ...") is a conflict between:

  1. wanting full semantic analysis which is aware of all relevant classes and
  2. wanting resilience if the build path does not contain all classes upon which the current class (indirectly) depends.

Obviously, JLS doesn't specify how compilers should handle incomplete build paths, but as a convenience for users, no errors should be reported if semantic analysis can avoid looking into certain indirect dependencies.

Where and when this can indeed be avoided needs to be checked (and implemented) on a case-by-case basis, but the given example likely qualifies as a case that can be avoided.

Until this issue is resolved, the problem can be avoided by making external-lib visible also to my-lib-B (e.g., using a project dependency). In module systems like OSGi or JPMS, it might actually be a good idea to let my-lib-A "re-export" its dependency external-lib, since its API class ClassA is "incomplete" for clients that are unable to see AbstractExternal.

Mikol answered 20/4, 2018 at 20:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.