Compiled into Fields as Bytecode

Dear all,

How can I get the vals and vars in my objects to compile into fields as pieces of bytecode? scalac (2.11) by default represents them as methods – I gathered using javap. Is there any way I can instruct it to do as I like instead? Any scalac command-line parameters? Code annotations?

TIA,
–Hossein

Do you mean public fields? Then I don’t think it’s possible. The only things that get compiled to (private) fields without methods are private[this] vals and vars.

As a matter of fact, I don’t quite know what it is that I should be looking for. My request here on this list comes from my conversation on another (Scala-unrelated) list. And, I am being almost verbatim. Here is an example for what I think was meant. Consider this code:

object O {
  val f = 0.0
}

When I javap O.class and O$.class, I get

public final class O {
  public static double f();
}

and

public final class O$ {
  public static final O$ MODULE$;
  public static {};
  public double f();
}

in both of which there is no mention of f except as methods. (And, it’s even worse if I make it private[this] because f completely vanishes then.) How can I get f to be a field in O.class or O$.class?

TIA,
–Hossein

It will be a field in almost all cases. You have to call javap -p to see private fields and methods.

Here is my Aha moment: So, Scala fields do get compiled into bytecode fields – albeit private. It only is that the public Scala ones also get the getter/setter pair of methods, whereas the rest don’t. Is that right?

And, what are the exceptions?

I think final val a = 42 becomes

public final int a() {
    return 42;
}

I’m not 100% sure.

That’s right. A public val gets a public accessor, and a public var gets a public accessor and public mutator. But they’re both backed by a private field.
Private vals and vars also get the methods but then they’re private as well. Private[this] is the exception, those only get a private field.

It makes sense too. If you compile

object O {
  val f = 0.0
}

to the equivalent of

public final class O {
  public static double f;
}

rather than

public final class O {
  private static double f;
  public static double f(){ return f;}
}

you have a public field that can be expected to be mutated.Since f is a val, you wouldn’t expect that to be possible.

Now if it were a var, I can’t see any direct reason why it needs accessors rather than expose the bare field - though that’s primarily a statement about me rather than about the implementation.

Interestingly (at least to me) the field is only used by its accessor for as far as I can see. Having another member access f in the object itself goes through the accessor as well. I wouldn’t be able to tell whether that introduces inefficiencies in jitted code (it at least seems like something the JVM would be good at optimizing, since it’s such a common pattern in Java), what the consequences on binary compatibility are.

Lastly, the really weird one to me is

object O {
  final val a = 1.2
}

which produces

scala> :javap -c -p -constants O
Compiled from "<console>"
public class O$ {
  public static final O$ MODULE$;

  private final double f;

  public static {};
    Code:
       0: new           #2                  // class O$
       3: invokespecial #12                 // Method "<init>":()V
       6: return

  public final double f();
    Code:
       0: ldc2_w        #16                 // double 1.2d
       3: dreturn

  public O$();
    Code:
       0: aload_0
       1: invokespecial #19                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #21                 // Field MODULE$:LO$;
       8: return
}

Getting f still goes through the accessor, but the accessor returns a constant rather than the field f, which is never read from at all - which is a good thing too, since it doesn’t get initialized either(!).