私有 var 构造函数参数和没有 val/var 的构造函数参数有什么区别?它们在范围/可见性方面是否相同?
前任:
class Person(private var firstName:String, lastName:String)
私有 var 构造函数参数和没有 val/var 的构造函数参数有什么区别?它们在范围/可见性方面是否相同?
前任:
class Person(private var firstName:String, lastName:String)
是的,有两个重要的区别。首先是简单的:没有var
orval
关键字的构造函数参数不是可变变量——它们的值不能在类的主体中更改。
但是,即使我们将自己限制为val
关键字,与无关键字参数之间仍然存在差异private val
。考虑以下:
class Person(private val firstName: String, lastName: String)
如果我们用 来查看编译后的类javap -v Person
,我们会发现它只有一个字段 for firstName
。lastName
只是一个构造函数参数,这意味着它可能在类初始化后被垃圾回收等。
编译器足够聪明,可以知道lastName
初始化后何时需要 的值,并在这种情况下为它创建一个字段。考虑以下变化:
class Person(private val firstName: String, lastName: String) {
def fullName = firstName + " " + lastName
}
编译器可以告诉它可能需要lastName
稍后的值,如果我们javap
再次检查,我们会看到该类有两个字段(注意,如果我们定义fullName
为 aval
而不是 a def
,它只有一个字段) .
最后,请注意,如果我们使用firstName
object-private而不是class-private,它的工作方式与普通的无关键字构造函数参数完全相同:
class Person(private[this] val firstName: String, lastName: String)
这甚至适用于var
而不是val
:
class Person(private[this] var firstName: String, lastName: String)
这两个类都没有字段。有关对象私有访问的更多详细信息,请参阅语言规范的第 5.2 节。
作为补充,如果你的类是case类,那么所有的构造函数参数都会自动成为public字段。
如果 private 关键字存在,编译器会报错,对于没有 val/var 的参数,无论是否在任何 defs 中使用,都会为它们生成公共字段。