Search code examples
groovyspock

def vs final def in Groovy


I've written simple test in Groovy using Spock framework

class SimpleSpec extends Specification {

    def "should add two numbers"() {
        given:
            final def a = 3
            final b = 4
        when:
            def c = a + b
        then:
            c == 7
    }
}

Variable a is declared using def and final keywords combination. Variable b is declared using only final keyword.

My question is: what's the difference (if any) between these two declarations? Should one approach be preffed to the other? If so, why?


Solution

  • User daggett ist right, final does not make a local variable final in Groovy. The keyword only has influence on class members. Here is a little illustration:

    package de.scrum_master.stackoverflow
    
    import spock.lang.Specification
    
    class MyTest extends Specification {
      def "Final local variables can be changed"() {
        when:
        final def a = 3
        final b = 4
        final int c = 5
        then:
        a + b + c == 12
    
        when:
        a = b = c = 11
        then:
        a + b + c == 33
      }
    
      final def d = 3
      static final e = 4
      final int f = 5
    
      def "Class or instance members really are final"() {
        expect:
        d + e + f == 12
    
        when:
        // Compile errors:
        // cannot modify final field 'f' outside of constructor.
        // cannot modify static final field 'e' outside of static initialization block.
        // cannot modify final field 'd' outside of constructor.
        d = e = f = 11
        then:
        d + e + g == 33
      }
    }
    

    When I switched one of my Spock projects to version 1.3 with Groovy 2.5 and noticed that this test no longer compiles now due to the compiler detecting the reassignment to final local variables. I.e. the inconsistency in Groovy <= 2.4 seems to be fixed.