2

This is a question about how Scala is compiled. Is there a way to get the compiled code to refer directly to var members (getfield, putfield) rather than going through accessor functions (invokespecial, _$eq$)?

I thought making the var final would do it, but no. Here's an example:

class foo {
  private final var x: Int = 0

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

and here is the output from 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
...

Or should I not care about this because the JVM will inline the accessors and the performance will be the same?

Here's the equivalent Java code:

class bar {
    private int x;

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

and bytecode:

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

  ...
Cotton Seed
  • 363
  • 3
  • 13

2 Answers2

4

You can use 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
}

You get

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

Note this usually leads to uglier code (imho), so if this kind of performance gain doesn't really matter, you should avoid it.

private[this] vs private

Community
  • 1
  • 1
Onilton Maciel
  • 3,559
  • 1
  • 25
  • 29
  • Thanks for the detailed answer and references. I don't get accessors with `private[this]` but I do with `private[foo]`. I guess `private[foo]` is the same as `private` in Java in terms of accessibility. – Cotton Seed Oct 31 '15 at 18:28
  • Updated the answer with the text from the reference that says what you observed. :) – Onilton Maciel Oct 31 '15 at 18:32
1

-- Or should I not care about this because the JVM will inline the accessors and the performance will be the same?

Yes, exactly.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38