Kotlin的internal关键字在Java互操作场景下的表现疑问
结论
你既没有遗漏配置,官方文档也不存在误导,是对名称修饰的生效场景理解存在偏差。
Kotlin
internal的底层实现逻辑
JVM 本身仅支持 public、protected、包私有、private 四种访问修饰符,没有和 Kotlin「模块级可见」匹配的原生修饰符。因此 Kotlin 编译器会将internal修饰的类、类成员统一编译为 public 级别,internal的可见性校验完全由 Kotlin 编译器在编译期完成:如果 Kotlin 代码跨模块访问其他模块的internal成员,编译器会直接抛出错误,不会通过编译。名称修饰的生效场景
文档提到的名称修饰,是为了避免 Java 代码绕过 Kotlin 编译器的校验,意外调用到其他模块的internal成员。该机制仅在跨模块访问时生效:
不同模块的internal成员即使签名完全一致,编译后成员名会被加上所属模块的唯一哈希后缀。你从外部 Java 项目中直接按原方法名调用时,会提示找不到对应方法,必须加上模块后缀才能成功调用,大幅降低了意外误用的概率。
你在本地测试时看到成员名没有变化,是因为所有代码都在同一个模块内编译,同一模块的internal成员不需要做名称修饰。
你可以自行验证:把测试的Foo类打包成独立jar,在另一个Java项目中依赖这个jar,尝试调用new Foo(1).foo(),就会收到编译错误,提示不存在foo()方法,实际可用的方法名是类似foo$module_name_hash的格式。关于
internal内部类的表现
你测试的内部类Bar本身被internal修饰,规则和顶级internal类完全一致:编译后为public类,跨模块从Java访问时,构造器会被名称修饰,无法直接按原签名调用。
内容的提问来源于stack exchange,提问作者Grzegorz Piwowarek

