Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Static fields in Scala (SI-4581)

Proposal

Fields annotated @scala.static are generated as static fields. The this identifier is not in scope in static field initialization expressions.

A static field x defined in a class C can be referenced as scala.static[C].x. If the field is variable, it can be updated as scala.static[C].x = t.

A static field y defined in a singleton object C can be directly referenced as C.x and updated as C.x = t.

Use Cases

Some JVM frameworks require classes to have specific static fields.

For example, classes extending android.os.Parcelable are required to have a static field named CREATOR of type android.os.Parcelable$Creator.

Another example is using an AtomicReferenceFieldUpdater.

Implementation

Field intialization expressions of static fields are added to the static initializer of the class (or the module class for static fields in objects).

The static[C] accessor can be implemented with scala.Dynamic, here's a sketch:

package scala

import scala.language.dynamics

class static extends annotation.StaticAnnotation

object static {
  object StaticSelection extends Dynamic {
    def selectDynamic(name: String)             = ??? // intercepted by the compiler
    def updateDynamic(name: String)(args: Any*) = ??? // me too
  }

  def apply[T: reflect.ClassTag] = StaticSelection
}

Open Questions

  • Can arbitrary (nested) classes and objects have static fields?
  • Feature interaction: serialization (readResolve of modules)

References

  • SI-4581 is a request for a @static annotation
  • #894 added the annotation, but was reverted in #1340.
    • This implementation was different: only fields in objects could be annotated @static. The static field was generated in the companion class (not in the module class).
  • A few bugs that showed up in the previous implementation (good test cases): SI-6189, SI-6236, SI-6294

Example

class C {
  @static var x = 0
  def inc = {
    static[C].x += 1
    static[C].x
  }
}

Generated pseudo-bytecode:

class C {
  static x: int
  
  method <clinit>: void = {
    setstatic x 0
  }
  
  method inc: int = {
    setstatic x ((getsatic x) + 1)
    getstatic x
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment