Does it make sense to mark variable as final in groovy?

17,883

Solution 1

As Justin has said, if the optimisations that the compiler performs for final variables are important to you, then you shouldn't be using Groovy.

However, if the performance of Groovy is good enough, then it is still useful to mark variables final for two reasons:

  • Protecting your class' invariants, i.e. making sure that a value cannot be changed after object construction. Java enforces this at compile-time, Groovy only enforces this at runtime, but this is better than silently allowing an immutable value to be changed

  • Documentation. Users of your class can easily see which values they are allowed to change

Solution 2

It doesn't appear that groovyc will inline final variables the way javac does. I created two test scripts, one using final and one not:

final String message = "Hello World"
println message
String message = "Hello World"
println message

javap -c produced the same output for both classes:

   0:   invokestatic    #18; //Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
   3:   astore_1
   4:   ldc #58; //String Hello World
   6:   astore_2
   7:   aload_1
   8:   ldc #59; //int 1
   10:  aaload
   11:  aload_0
   12:  aload_2
   13:  invokeinterface #63,  3; //InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object;
   18:  areturn
   19:  nop

javac optimized away the astore/aload:

Without final:

   0:   ldc #2; //String Hello World
   2:   astore_1
   3:   getstatic   #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   6:   aload_1
   7:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:  return

With final:

   0:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc #3; //String Hello World
   5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

All that said, if performance is paramount, Groovy is a poor choice to begin with. Inlining final variables won't save you from the overhead of using reflection for method calls.

Solution 3

not yet. but it might in a future, so I still mark them if appropriate.

https://issues.apache.org/jira/browse/GROOVY-1628

Share:
17,883
Skarab
Author by

Skarab

BY DAY: System Engineer, software craftsman BY AFTERNOON, BY WEEKEND: lecturer, student enchanter for software engineering, cloud tech, devOps, ... , and SAP ABAP :D

Updated on June 05, 2022

Comments

  • Skarab
    Skarab about 2 years

    I wonder how variables marked as final are interpreted by Groovy (in 1.8.0, 1.8.1). I know that it makes sense in Java and it is possible to improve the performance and -- of course -- help to avoid stupid mistakes. I would like to learn if final may help the java compiler to optimize a program written in Groovy. I wonder if Groovy transformers preserve the final markings for variables.

  • Skarab
    Skarab almost 13 years
    Thx, regarding your last statement, I am aware of the fact that Groovy is much slower than Java or Scala.
  • Skarab
    Skarab over 12 years
    The current version of Groovy (1.8.2) does not care about final and it does not enforce anything.
  • Erik Madsen
    Erik Madsen about 10 years
    I've heard a lot of late about how groovy is starting to gain on performance. Does the above still reflect the picture as of Groovy 2.2 or versions on the roadmap?