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中使用的非导出类型.但是,我不认为目前有什么. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |