Kotlin主构造函数无val/var的参数本质是什么?
Kotlin主构造函数参数:带val/var与不带的核心区别
不带val/var的构造参数本质是什么?
不带val/var的主构造函数参数,只是构造函数的局部临时参数——它们的作用域仅限于类的初始化阶段,也就是:
- 类的属性初始化表达式(比如你第三段代码里的
val fullname = "Mr. $name") - 初始化块
init{}内部 - 次构造函数的代码逻辑中
一旦类的初始化完成,这些参数就会被销毁,不再处于任何作用域内,所以无法在成员函数(比如greet())或类外部访问。
三段代码的差异解析
第一段代码(编译失败)
class A constructor (name: String) { fun greet() { println("hello $name") } }
greet()是类的成员函数,调用它的时候类已经完成初始化,name这个临时参数早已不存在,所以编译器提示“未解析的引用”——就像你在C++里试图在成员函数中访问构造函数的普通形参,或者在Python里试图在__init__之外访问它的局部参数,必然报错。
第二段代码(编译成功)
class A constructor (val name: String) { fun greet() { println("hello $name") } }
当你给构造参数加上val(或var)时,Kotlin会自动帮你完成两件事:
- 在类内部创建一个对应的私有字段
- 生成公共的getter方法(如果是
var还会生成setter)
简单说,val name直接把这个参数提升为类的只读属性,它的生命周期和类实例绑定,所以成员函数里能访问,外部也能通过A("ken").name读取它的值。
第三段代码(编译成功)
class A constructor (name: String) { val fullname = "Mr. $name" fun greet() { println("hello $fullname") } }
fullname的初始化表达式是在类的初始化阶段执行的,此时name这个临时参数还在作用域内,所以可以正常引用。初始化完成后name被销毁,但fullname已经成为类的属性,所以greet()里能访问fullname,却不能直接用name。
结合你的C++/Python经验类比
- C++视角:不带
val的参数等价于构造函数的普通形参,只能在构造函数体(包括初始化列表)中使用;带val的参数等价于你手动声明了类成员变量,然后在构造函数中赋值给它,Kotlin帮你简化了这个流程。 - Python视角:不带
val的参数类似__init__方法的局部参数,只在__init__内部有效;带val的参数等价于你在__init__里写了self.name = name,把参数绑定为实例属性,Kotlin自动完成了这个绑定操作。
关键总结
- 不带
val/var:临时构造参数,仅初始化阶段可用,非类属性 - 带
val:只读类属性,自动生成字段和getter,全生命周期可访问 - 带
var:可读写类属性,自动生成字段、getter和setter,全生命周期可访问
内容的提问来源于stack exchange,提问作者longhaulblue
相关产品推荐
相关产品推荐

