加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 为什么公共API泄漏内部类型的编译不会失败?

发布时间:2020-12-14 05:20:26 所属栏目:Java 来源:网络整理
导读:我有以下 Java 9模块: module com.example.a { exports com.example.a;} 使用导出类型: public class Api { public static void foo(ImplDetail args) {}} 和一个非导出类型: package com.example.b.internal;public class ImplDetail {} 导出的类型在公
我有以下 Java 9模块:
module com.example.a {
    exports com.example.a;
}

使用导出类型:

public class Api {

    public static void foo(ImplDetail args) {}
}

和一个非导出类型:

package com.example.b.internal;

public class ImplDetail {}

导出的类型在公共方法中使用非导出类型作为方法参数类型.我假设编译器会拒绝这种不一致的类配置,因为其他模块中的客户端无法真正调用foo()方法,因为它们不能实例化参数类型.

令我惊讶的是,这个模块是由javac编译成功的.我可以看到传递null的特殊情况,仍然会考虑这样的API定义格式错误,并认为它不应该被支持,由编译器理想地执行.

不禁止这种情况的原因是什么?

解决方法

当然,在API中使用非导出类型是不好的风格,很有可能是设计错误,但是我相当清楚的是,javac不能使它成为编译时错误.

请注意,一直有可能在公共API中使用私有类型,一直返回到Java 1.0.

您已经注意到模块外的代码仍然可以调用Api.foo(null).

还有一些情况下,调用者仍然可以使用非空引用的API.考虑一个类public class Sub在包com.example.a中扩展ImplDetail.这个类Sub是public的,并且被导出,因此可以在模块之外进行编码.因此,外部代码可以使用从某处获取的Sub的实例调用Api.foo(sub).

但是肯定的是,javac可以告诉任何导出的包中是否存在ImplDetail的子类,如果没有,则会发出编译时错误?不必要.由于单独编译的可能性,在包含Api的编译步骤之后,可能会将新类引入到模块中.或者,为此,可以重新编译module-info.class文件以更改导出的包的集合.

由于这些原因,我认为javac在编译Api类时引发错误是不合适的.然而,Javac确实有一个选项-Xlint:exports,它会将这种情况标记为警告.

在构建过程中,如jmod工具或某些事后模块审核工具之后,还可以标记在导出的API中使用的非导出类型.但是,我不认为目前有什么.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读