6

问题设置由三个 java 库组成(为了便于阅读,我删除了所有包名,到处都使用全限定名):

  1. external-lib:提供抽象类

    public abstract class AbstractExternal {}
    
  2. my-lib-A:提供类

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

    external-lib在 my-lib-A 的类路径中。

  3. my-lib-B 从 ClassA 静态导入 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),当将 ClassB 修改为

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 ClassAClassA.FOO

问题 2:为什么import static ClassA.FOO当它从 my-lib-A 扩展另一个类然后扩展 AbstractExternal 时会起作用?

编辑:重要信息:有问题的编译器是Eclipse Compiler for Java (ECJ)。

编辑 2:javac 与 ECJ 同步,并且能够在静态导入失败时编译 ClassB 中的正常导入和类访问。

4

1 回答 1

2

Ecj 理想情况下“不应该”报告此错误。我提交了错误 533890来跟踪它。

此消息的所有错误背后的共同主题(“......无法解决。它被间接引用......”)是以下之间的冲突:

  1. 想要了解所有相关类的完整语义分析,并且
  2. 如果构建路径不包含当前类(间接)依赖的所有类,则需要弹性。

显然,JLS 并没有规定编译器应该如何处理不完整的构建路径,但为了方便用户,如果语义分析可以避免查看某些间接依赖关系,则不应报告错误。

何时何地确实可以避免这种情况需要根据具体情况进行检查(和实施),但给定的示例可能有资格作为可以避免的情况

在解决此问题之前,可以通过使external-lib也可见my-lib-B(例如,使用项目依赖项)来避免该问题。my-lib-A在像 OSGi 或 JPMS 这样的模块系统中,让“重新导出”其依赖关系实际上可能是一个好主意external-lib,因为它的 API 类对于无法看到的客户端来说ClassA “不完整的” AbstractExternal

于 2018-04-20T20:42:45.037 回答