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

前端之家收集整理的这篇文章主要介绍了java – 为什么公共API泄漏内部类型的编译不会失败?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有以下 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中使用的非导出类型.但是,我不认为目前有什么.

原文链接:https://www.f2er.com/java/122871.html

猜你在找的Java相关文章