Java转Kotlin:含内部Builder的类访问Builder私有成员的惯用法方案
适配Kotlin访问规则的低改动实现方案
自动迁移的代码报错本质是Kotlin与Java对嵌套类私有成员的可见性规则定义不同:Java允许外部类与其静态嵌套类互相访问私有成员,Kotlin仅支持外部类访问自身声明的嵌套类私有成员,反过来嵌套类的私有成员对外部类是完全封闭的。
下面两种方案都不需要对原有建造者的核心逻辑做大规模重构,改动量极小且完全符合Kotlin惯用风格:
方案1:最小改动量适配
- 操作方式:仅把Builder类中需要被Outer类读取的
mValue字段的修饰符从private改为internal,其余代码完全保持迁移后的原样即可解决编译问题。 - 特性说明:
internal是Kotlin的模块级可见修饰符,字段不会暴露给模块外部的调用方,和原Java代码中私有字段的对外封闭性几乎没有差异。如果需要进一步限制同模块其他类的非必要访问,配合简单的代码检查规则即可规避越权读写。 - 对应改动的代码段:
class Builder { // 仅替换修饰符,其余逻辑不变 internal var mValue = 0 fun setValue(value: Int): Builder { mValue = value return this } fun build(): Outer { return Outer(this) } }
方案2:完全保持字段私有封闭性
- 操作方式:不调整Builder类中
mValue的私有修饰符,仅将原Outer构造器直接读取Builder内部字段的逻辑,调整为Builder在调用Outer构造器时,主动把自身持有的私有配置值传递过去。既保持了Builder内部字段的完全私有状态,也符合建造者“由Builder负责维护配置、传递配置值,目标类不需要感知Builder内部实现”的基本逻辑。 - 特性说明:调整后对外提供的Builder链式调用接口、Outer类的实例方法完全不变,外部使用代码不需要做任何修改,也不会向外暴露任何内部字段的访问入口,是Kotlin里实现同类建造者的常用写法。
- 调整后的完整可编译代码:
import java.io.PrintStream class Outer private constructor(mValue: Int) { private val mValue: Int fun printValue(stream: PrintStream) { stream.println(mValue) } class Builder { // 保持原有private修饰符,不做任何可见性改动 private var mValue = 0 fun setValue(value: Int): Builder { mValue = value return this } fun build(): Outer { // 由Builder主动传递自己维护的私有值 return Outer(mValue) } } init { this.mValue = mValue } }
内容的提问来源于stack exchange,提问作者msbit
相关产品推荐
相关产品推荐

