当导入的类扩展第 3 方库时,Java 导入静态失败

标签 java inheritance static-import ecj

问题设置由三个 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 行产生以下错误:

无法解析 AbstractExternal 类型。它是从所需的 .class 文件中间接引用的

但是(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 ClassA with ClassA.FOO 有效?

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

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

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

最佳答案

Ecj 理想情况下“不应该”报告这个错误。我提交了 Bug 533890跟踪这个。

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

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

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

何时何地确实可以避免这种情况需要根据具体情况进行检查(和实现),但给出的示例可能符合可以避免的情况。

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

关于当导入的类扩展第 3 方库时,Java 导入静态失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49859548/

相关文章:

c++ - 模板化类型定义和继承

java - c#中的静态导入

java.lang.ArrayIndexOutOfBoundsException : 49 error - NFA Java 异常

java - 获取 Super 的属性值而不是实际对象

java - Selenium:- 无法在文本框中写入

javascript - 如何在javascript中正确继承?

java - 静态导入日历对象数组(无法初始化)

java - 静态导入文件或静态导入单个项目

java - Java中的Apache Ignite中的空拓扑

java - @ViewScoped 在开发模式下工作,但在生产模式下不起作用