简答
不,没有任何性能优势。 private def 和 private[this] def 都被转换为字节码中的 private 或 public 方法,这取决于它们是否从不同的类中调用,而不取决于它们在 Scala 中的可见性。
理论
让我们从Scala language specification 对private[this] 的评价开始:
它只能从定义它的对象中访问。也就是说,选择 p.M 仅当前缀是 this 或 O.this 时才合法,对于包含引用的某些类 O。此外,适用于不合格私人的限制。
您可以看到规范只是说明了语法上可接受与否的内容。 private 和private[this] 都只能从同一类或内部类的实例中调用。在字节码中,您只能区分类级别的访问,而不是实例级别。因此,两个选项在字节码中应该是相同的,而 Scala 仅在编译期间强制执行差异。
基本情况
首先,我们来看一个简单的例子:
class MyClass {
private def privateDef(x: Int) = x
private[this] def privateThisDef(x: Int) = x
}
这被翻译成字节码
public class MyClass {
private int privateDef(int);
private int privateThisDef(int);
public MyClass();
}
如您所见,两种方法都以private 结尾,因此从 JVM 的角度来看没有区别(例如,关于内联、静态/动态绑定等)。
内部类
当我们添加内部类时,这会发生什么变化?
class MyClass {
private def privateDef(x: Int) = x
private[this] def privateThisDef(x: Int) = x
class MyInnerClass{
MyClass.this.privateDef(1)
MyClass.this.privateThisDef(2)
}
}
这被翻译成
public class MyClass {
public int MyClass$$privateDef(int);
public int MyClass$$privateThisDef(int);
public MyClass();
}
public class MyClass$MyInnerClass {
public final MyClass $outer;
public MyClass MyClass$MyInnerClass$$$outer();
public MyClass$MyInnerClass(MyClass);
}
你可以看到这次MyClass中的两个方法都是public的,所以内部类可以调用它们。同样,private 和 private[this] 之间没有区别。
同伴
当可以从不同的类调用私有方法时,Scala 添加了一种特殊情况 - 当您从其各自类中的伴随对象调用私有方法时。 MyClass 的伴随对象将是一个单独的类,以字节码命名为 MyClass$。在同伴中调用private 方法会跨越类边界,因此此类方法将在字节码中公开。
你不能在同伴之外调用private[this] 方法,但这只是一个语法限制。无论您可以在private 和private[this] 之间进行选择,结果在字节码中都是相同的。
变量
vars 的行为似乎与 defs 的行为有些不同。本课
class MyClass {
private var privateVar = 0
private[this] var privateThisVar = 0
private var privateVarForInner = 0
private[this] var privateThisForInner = 0
class MyInnerClass{
privateVarForInner = 1
privateThisForInner = 1
}
}
编译成
public class MyClass {
private int privateVar;
private int privateThisVar;
private int MyClass$$privateVarForInner;
public int MyClass$$privateThisForInner;
// ...
}
然后内部类对privateVar 使用setter,对privateThisVar 使用字段访问。我不确定为什么 scalac 会这样,我在规范中没有找到任何东西。也许这是特定于实现的东西。
编辑: 根据要求,我创建了一个小型 JMH benchmark,比较了获取和设置 private var 和 private[this] var 的性能。结果?根据JMH,所有操作都是≈ 10⁻⁸s。差异可以忽略不计,无论如何,内部类和vars 的情况很少见。