Scala 直接会员访问

Scala direct member access

这是一个关于Scala是如何编译的问题。有没有办法让编译后的代码直接引用 var 成员(getfield、putfield)而不是通过访问器函数(invokespecial、_$eq$)?

我以为让 var final 就可以了,但是不行。这是一个例子:

class foo {
  private final var x: Int = 0

  def incr { x += 1 }
  def result: Int = x
}

这里是 javap 的输出:

Compiled from "foo.scala"
public class foo {
  private int x;

  private final int x();
    Code:
       0: aload_0
       1: getfield      #13                 // Field x:I
       4: ireturn

  private final void x_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #13                 // Field x:I
       5: return

  public void incr();
    Code:
       0: aload_0
       1: aload_0
       2: invokespecial #22                 // Method x:()I
       5: iconst_1
       6: iadd
       7: invokespecial #24                 // Method x_$eq:(I)V
      10: return
...

或者我不应该关心这个,因为 JVM 将内联访问器并且性能是一样的?

这是等效的 Java 代码:

class bar {
    private int x;

    void incr() { x += 1; }
    int result() { return x; }
}

和字节码:

final class bar {
  private int x;

  void incr();
    Code:
       0: aload_0
       1: dup
       2: getfield      #2                  // Field x:I
       5: iconst_1
       6: iadd
       7: putfield      #2                  // Field x:I
      10: return

  ...

-- 或者我不应该关心这个,因为 JVM 将内联访问器并且性能是一样的?

是的,完全正确。

您可以使用 private[this] ref :

...

A private[C] where C is the outermost enclosing class is the same as just private in Java.

Finally, Scala also has an access modifier that is even more restrictive than private. A definition labeled private[this] is accessible only from within the same object that contains the definition. Such a definition is called object-private.

...

class foo {                                                                                                                                             
  private[this] final var x: Int = 0

  def incr { x += 1 }
  def result: Int = x
}

你得到

Compiled from "foo.scala"
public class foo {
  private int x;
  public void incr();
  public int result();
  public foo();
}

请注意,这通常会导致代码更丑陋(恕我直言),因此如果这种性能提升并不重要,您应该避免使用它。

private[this] vs private