Kotlin调用私有构造器报Cannot access <init>的原因及<init>含义
<init>的具体指代 你在报错里看到的<init>不是Kotlin代码层面定义的方法名,是JVM字节码规范里定死的实例初始化方法的内部命名,所有跑在JVM上的语言(Kotlin、Java都算),类里写的每一个构造方法编译成字节码后,都会对应生成一个签名匹配的<init>方法:
- 这个方法执行的时候,会按顺序完成类实例属性的初始赋值、初始化块里的逻辑运行、构造函数内写的自定义逻辑,最终把初始化完成的对象返回
- 容易搞混的是同属字节码固定命名的
<clinit>,这是类级别的静态初始化方法,负责处理伴生对象常量、静态代码块这类类加载阶段就会跑的逻辑,和实例创建没关系。
触发"Cannot access
<init>"报错的根本原因 这个报错本质就是普通的私有成员访问权限不通过,结合代码场景拆解逻辑非常清晰:
- 你给
Person的主构造加了private修饰符,编译后对应的<init>构造方法访问权限就被设为私有,按照Kotlin的访问规则,私有成员只允许在类自身的内部作用域调用。
对应类代码:
class Person private constructor(val firstName:String , val lastName: String) { companion object { fun createPerson(firstName: String, lastName: String): Person { return Person(firstName, lastName) } } }
- 伴生对象里的工厂方法
createPerson能正常调用构造,是因为伴生对象本身就是Person类绑定的内部成员,天然持有外部类所有私有成员的访问权限,所以在这里调用私有构造完全合法:
// 合法调用,正常运行 val person1 = Person.createPerson("Niels", "Abel")
- 你在类外部直接写
Person("Évariste", "Galois")的时候,本质是绕过公开的工厂方法,直接调用被标记为私有的<init>构造方法,编译器做权限校验时发现当前作用域没有访问私有成员的资格,就会抛出对应错误:
// 编译不通过,触发报错 val person2 = Person("Évariste", "Galois")
至于为什么报错里直接显示
<init>而不是显示你写的constructor,只是因为编译器做检查时直接读了字节码层面的方法标识,没有额外做一层面向开发者的名称转换而已,没有什么特殊逻辑。
内容的提问来源于stack exchange,提问作者shenun
相关产品推荐
相关产品推荐

