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-lib
is 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-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.
by Joshua Bloch.) This is considered bad Java programming practice because when a class implements an interface, it becomes part of the class's public API. Implementation details, such as using the static members of another class, should not leak into public APIs.
Static import is a feature introduced in the Java programming language that allows members (fields and methods) which have been scoped within their container class as public static , to be used in Java code without specifying the class in which the field has been defined.
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes.
What is the difference between import and static import? The import allows the java programmer to access classes of a package without package qualification whereas the static import feature allows to access the static members of a class without the class qualification.
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-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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With