Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 473
Skarab Avatar asked Aug 24 '11 14:08

Skarab


People also ask

Why should I make variables final?

Effectively Final A variable is effectively final if it isn't explicitly declared final but its value is never changed after initialization. The main purpose of effectively final variables is to enable lambdas to use local variables that are not explicitly declared final.

What happens when you make a variable final?

Once we declare a variable with the final keyword, we can't change its value again. If we attempt to change the value of the final variable, then we will get a compilation error. Generally, we can consider a final variable as a constant, as the final variable acts like a constant whose values cannot be changed.

Can we declare variable as final?

In Java, we can use final keyword with variables, methods, and classes. When the final keyword is used with a variable of primitive data types such as int, float, etc), the value of the variable cannot be changed.

Should method variables be final?

Method parameters and local variables should not be declared final unless it improves readability or documents an actual design decision. Fields should be declared final unless there is a compelling reason to make them mutable.


2 Answers

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.

like image 67
Justin Piper Avatar answered Sep 18 '22 15:09

Justin Piper


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

like image 20
Dónal Avatar answered Sep 21 '22 15:09

Dónal