Let's consider the following:
object Foo {
val BUFFER_SIZE = 1024
}
class Foo {
.
.
.
val buffer = new Array[Byte](Foo.BUFFER_SIZE)
This is too verbose and doesn't seem to be elegant compared with Java's static (final) variable, especially because the definition and the usage of the constant are too far apart to understand the code immediately. What I want is something like this:
class Foo {
val BUFFER_SIZE = 1024
val buffer = new Array[Byte](BUFFER_SIZE)
The question is, is the Scala compiler smart enough to not instantiate BUFFER_SIZE for every instance of Foo to waste time and space? Or should go with the first one?
TLDR: No, it is not so good, but you can guide the compiler.
And it's easy to check (I put the code into test.scala):
scalac test.scala
javap Foo.class
// Compiled from "test.scala"
// public class Foo {
// public int BUFFER_SIZE();
// public byte[] buffer();
// public Foo();
// }
So val ends up to be a getter method. Now let's look at the actual bytecode:
javap -c Foo.class
Compiled from "test.scala"
public class Foo {
public int BUFFER_SIZE();
Code:
0: aload_0
1: getfield #15 // Field BUFFER_SIZE:I
4: ireturn
// .... irrelevant parts
As you can see there is a getfield
code that means there will be distinct instance for every class instance (versus getstatic
which means access to static variable).
Highly optimized code would look like
public final int BUFFER_SIZE();
Code:
0: sipush 1024
3: ireturn
which will be produced if you mark BUFFER_SIZE with final
modifier:
class Foo {
final val BUFFER_SIZE = 1024
val buffer = new Array[Byte](BUFFER_SIZE)
}
Prefixing field with private[this]
as @ghik said will do the trick as well. The difference is that final
produces getter with trivial code, whereas private[this]
directly inlines value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With