问题设置由三个java库组成(为了可读性,我删除了所有包名称,到处都使用完整的限定名):
-
外部库:提供抽象类
public abstract class AbstractExternal {}
-
my-lib-A:提供类
public class ClassA extends AbstractExternal { public static final String FOO = "foo"; }
external-lib
在 my-lib-A 的类路径中。 -
my-lib-B 从 A 类静态导入 FOO:
import static ClassA.FOO; public class ClassB { private String foo = FOO; }
my-lib-A
在 my-lib-B 的类路径中,但external-lib
不是。
问题:import static
行生成以下错误:
The type AbstractExternal cannot be resolved. It is indirectly referenced from required .class files
.
但是 (1),当将 B 类修改为
import ClassA;
public class ClassB {
private String foo = ClassA.FOO;
}
编译器很高兴。
但是(2),当添加第二个抽象时,两个my-lib-A类似
public class AbstractClassA extends AbstractExternal {}
和
public class ClassA extends AbstractClassA {
public static final String FOO = "foo";
}
上面示例中 ClassA.FOO 的静态导入有效。
问题1:为什么import static ClassA.FOO
在import ClassA
ClassA.FOO
工作时失败?
问题 2:为什么当import static ClassA.FOO
从 my-lib-A 扩展另一个类然后扩展 AbstractExternal 时会起作用?
编辑:一个重要的信息:有问题的编译器是Eclipse Compiler for Java(ECJ)。
编辑 2:javac 与 ECJ 同步,能够在静态导入失败时编译 B 类中的正常导入和类访问。
Ecj 理想情况下"不应该"报告此错误。我提交了错误 533890 来跟踪这一点。
此消息的所有错误背后的共同主题("...无法解决。它被间接引用...")是以下两者之间的冲突:
- 想要完整的语义分析,知道所有相关的类和
- 如果生成路径不包含当前类(间接)依赖的所有类,则希望复原。
显然,JLS 没有指定编译器应如何处理不完整的构建路径,但为了方便用户,如果语义分析可以避免查看某些间接依赖项,则不应报告任何错误。
何时何地确实可以避免这种情况需要逐案检查(和实施),但给定的示例可能有资格成为可以避免的情况。
在解决此问题之前,可以通过使external-lib
也对my-lib-B
可见(例如,使用项目依赖项)来避免该问题。在像OSGi或JPMS这样的模块系统中,让my-lib-A
"重新导出"其依赖项external-lib
实际上可能是一个好主意,因为它的API类ClassA
对于无法看到AbstractExternal
的客户端来说是"不完整的"。