使用包含非导出参数类型的方法的接口实现(Java 9模块)

时间:2016-12-02 02:02:43

标签: java java-9 jigsaw

我正在使用Java 9模块系统。以下是我的问题的简化版本。

我已定义ClassA(在模块com.foo中)以实现InterfaceB(在模块com.bar中)。 ClassA实现print的{​​{1}}方法,该方法采用InterfaceB类型的参数(在模块ClassC中)。以下是代码。

com.baz

// src/a/com/foo/ClassA.java package com.foo; import com.bar.InterfaceB; import com.baz.ClassC; public class ClassA implements InterfaceB { @Override public void print(ClassC obj) { System.out.println(obj); } } // src/b/com/bar/InterfaceB.java package com.bar; import com.baz.ClassC; public interface InterfaceB { public void print(ClassC obj); } // src/c/com/baz/ClassC.java package com.baz; public class ClassC { @Override public String toString() { return "This is a ClassC object"; } } 模块不会导出任何内容。因此,为了在编译com.bazClassC期间访问InterfaceB,我使用了ClassA标记。

--add-exports成功编译,但当我尝试编译InterfaceB时,收到错误:

ClassA

编译器是否以某种方式使用src/a/com/foo/ClassA.java:6: ClassA is not abstract and does not override abstract method print(ClassC) in InterfaceB 的不同实例?我感觉ClassC发生了意想不到的事情。

(作为旁注,我使用--add-exports的原因是,在我的示例中,--add-exports实际上是一个内部JDK包。我无法将模块设置修改为出口它。)

2 个答案:

答案 0 :(得分:4)

虽然确实有办法让模块系统编译代码(you found it already),但是在运行时会发现类似的问题,同时代码调用InterfaceB::print无法访问{{1 }}。同样,命令行标志可用于修复它。 但他们不应该!

模块系统试图告诉你一些事情,在这里:"这种模块化被破坏了!"

如果 ClassC以外的任何模块应该被允许使用com.baz,那么应该导出包含它的包!这正是出口的目的。其他代码显然依赖于ClassC,并且构建模块系统以使这些依赖性显式化。因此,除非您在练习中了解命令行覆盖,否则真正的解决方案是让 com.baz 导出ClassC

(如果不是所有模块都应该看到它,请考虑qualified exports。如果涉及反思,其他方法可能更适合,应该提出新问题。)

答案 1 :(得分:0)

我仍然不确定错误发生的原因或是否有意,但我确实找到了解决方案。

在编译ClassA时,com.baz模块导出到com.bar(其中InterfaceB)似乎允许编译器看到纠正ClassC类。

e.g。

-javac ... --add-exports com.baz/com.baz=com.foo,com.bar