Scala 直接成员访问

标签 scala compilation jvm

这是一个关于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

  ...

最佳答案

您可以使用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

关于Scala 直接成员访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33453662/

相关文章:

scala - FoldLeft 总和值与 BigDecimal.ZERO 起始值

java - maven 中的 IntelliJ 目录小蓝点标签

scala - 如果列表存在,获取列表尾部的简单简洁方法是什么?

c - 处理警告: implicit declaration of function ‘sigignore’

linux - Emacs 编译缓冲区显示引号的十六进制值

java - java 虚拟机崩溃时,可以将 hs_err_pid*.log 写入特定目录(不同于类目录)吗?

java - 解决 JVM "Incompatible object argument for function call"错误(javassist 检测)

Scala REPL 无法导入包

java - Heroku 编译参数

java - System.out.println 最终阻塞