繁体   English   中英

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

[英]Interface implementation with a method containing a non-exported parameter type (Java 9 modules)

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

我已经定义了ClassA (在模块com.foo )来实现InterfaceB (在模块com.bar )。 ClassA实现了InterfaceB的方法print ,它接受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.baz模块不会导出任何内容。 因此,为了在编译InterfaceBClassA期间访问ClassC ,我使用了--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的原因是,在我的例子中, com.baz实际上是一个内部JDK包。我无法修改模块设置以导出它。)

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

模块系统试图告诉你一些事情,在这里: “这种模块化已被打破!”

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

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

我仍然不确定为什么会出现错误或是否有意,但我确实找到了解决方案。

虽然编译ClassA导出com.baz模块com.bar (其中InterfaceB是)似乎让编译器看到正确的ClassC类。

例如

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM