`private [this] def`什么时候比'private def`更具性能优势?

0__*_*0__ 13 performance visibility scala

private[this] def与仅仅相比,写作在性能与噪声比方面是否有意义private def?我的理解是,使有关差别private[this] valprivate val,因为前者允许scalac创建一个实际的领域.但也许因为def它没有区别?最后,怎么样private[this] var

有一个非常相似的问题,但它没有包含有关性能的具体陈述.

Mif*_*eet 5

简短的回答

不,没有任何性能优势.双方private defprivate[this] def会转换为privatepublic取决于它们是否来自一个不同的类调用,而不是根据什么他们在斯卡拉能见度在字节码的方法.

理论

让我们从Scala语言规范所说的内容开始private[this]:

它只能从定义它的对象中访问.也就是说,选择pM仅在前缀为this或O.this时才合法,对于包含引用的某个类O. 此外,对不合格私人的限制适用.

您可以看到规范只是说出语法上可接受的内容.二者privateprivate[this]可以从同一类或内类的实例仅调用.在字节码中,您只能区分类级别的访问,而不是实例级别.因此,两个选项在字节码中应该相同,Scala仅在编译期间强制执行差异.

基本情况

首先,让我们看一个简单的例子:

class MyClass {
    private def privateDef(x: Int) = x
    private[this] def privateThisDef(x: Int) = x
}
Run Code Online (Sandbox Code Playgroud)

这被转换为字节码为

public class MyClass {
   private int privateDef(int);
   private int privateThisDef(int);
   public MyClass();
}
Run Code Online (Sandbox Code Playgroud)

如您所见,两种方法最终都是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)
  }
}
Run Code Online (Sandbox Code Playgroud)

这被翻译成了

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);
}
Run Code Online (Sandbox Code Playgroud)

你可以看到,这次,两个方法MyClass都是公共的,以便内部类可以调用它们.再次,private和之间没有区别private[this].

同伴

当一个私有方法可以从另一个类调用时 - 当你从它的各个类中的一个伴随对象调用一个私有方法时,Scala又增加了一个特殊情况.一个伴随对象MyClass将是一个以MyClass$字节码命名的单独类.private在伴随中调用方法会跨越类边界,因此这种方法将在字节码中公开.

你不能private[this]在同伴之外调用方法,但这只是一种语法限制.无论您在哪里private和之间进行选择private[this],结果在字节码中都是相同的.

瓦尔

变量的行为似乎与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
  }
}
Run Code Online (Sandbox Code Playgroud)

被编译为

public class MyClass {
  private int privateVar;
  private int privateThisVar;
  private int MyClass$$privateVarForInner;
  public int MyClass$$privateThisForInner;
  // ...
}
Run Code Online (Sandbox Code Playgroud)

然后内部类使用setter for privateVar和field access privateThisVar.我不确定scalac为什么会这样,我在规范中找不到任何东西.也许这是特定于实现的东西.

编辑:根据要求,我创建了一个小的JMH 基准,比较获取和设置a private var和的性能private[this] var.结果?? 10??根据JMH,所有操作都是根据.差异可以忽略不计,内部类和vars的情况无论如何都是罕见的.