Kotlin允许方法内声明与参数同名变量的原因及隐藏参数访问方法
好问题!这其实涉及到Kotlin的作用域与标识符屏蔽(shadowing)规则,咱们一步步来理清楚~
为什么Kotlin允许方法内部声明与参数同名的变量?
Kotlin的作用域是嵌套层级式的:方法的参数属于「函数参数作用域」,而方法内部声明的局部变量属于「局部作用域」,后者嵌套在前者之内。当局部作用域里出现和外层作用域同名的标识符时,就会发生屏蔽——局部变量会“覆盖”外层的参数,此时在局部作用域内访问这个名称,只会指向局部变量。
这种设计是很多编程语言的常见选择,原因主要有两点:
- 开发者有时确实需要在局部复用名称,比如对参数进行类型转换、重新定义值(如果参数是
val,局部变量可以用同名但不同类型/值),不需要特意想新的变量名; - 只要开发者清楚作用域的层级关系,就能避免意外问题,Kotlin选择信任开发者的判断力,没有强行禁止这种写法。
比如你给出的示例:
fun main(args: Array<String>) { val args = Any() }
这里局部的args就屏蔽了参数的args,在main函数内部后续访问args,都会指向那个Any类型的局部变量。
是否存在访问被“隐藏”参数的方法?
这得分两种情况来看:
- 如果是类的成员函数:可以用
this关键字来引用被屏蔽的参数。因为成员函数的参数属于类的实例,this指向当前实例,通过this.参数名就能绕过局部变量的屏蔽,直接访问参数。举个例子:class Example { fun test(input: String) { val input = "局部变量" println(input) // 输出:局部变量 println(this.input) // 输出:原来的参数值 } } - 如果是顶层函数(比如你的
main函数):因为顶层函数没有所属的实例,也就没有this可以用,所以一旦局部变量屏蔽了参数,就没办法直接访问原来的参数了。这时候的解决办法是在屏蔽之前,把参数的值存到另一个变量里,比如:fun main(args: Array<String>) { val originalArgs = args // 先把参数保存到新变量 val args = Any() println(originalArgs) // 这里就能访问原来的参数了 }
内容的提问来源于stack exchange,提问作者the_kaba
相关产品推荐
相关产品推荐

