The problem setup consists of three java libs (I stripped all package names for readability, full qualified names are used everywhere):
external-lib: provides the abstract class
public abstract class AbstractExternal {}my-lib-A: provides the class
public class ClassA extends AbstractExternal { public static final String FOO = "foo"; }external-libis in my-lib-A's classpath.my-lib-B statically imports FOO from ClassA:
import static ClassA.FOO; public class ClassB { private String foo = FOO; }my-lib-Ais in my-lib-B's classpath butexternal-libis 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.
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:
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-libvisible also tomy-lib-B(e.g., using a project dependency). In module systems like OSGi or JPMS, it might actually be a good idea to letmy-lib-A"re-export" its dependencyexternal-lib, since its API classClassAis "incomplete" for clients that are unable to seeAbstractExternal.