Re: GEP-16: val keyword for final declarations

Jochen Theodorou <[email protected]> Wed, 15 Apr 2026 13:29:38 +0200
Newsgroups gmane.comp.lang.groovy.devel
Message-ID <[email protected]>
On 4/12/26 13:59, Paul King wrote:
> Hi folks,
> 
> We have been asked numerous times about the possibility of having a 
> "val" keyword to match Kotlin and Scala. We also have had a related Jira 
> open for more than 6 years. So I created a GEP to help frame a 
> discussion about what would be involved and help us make a decision:
> 
> https://groovy.apache.org/wiki/GEP-16.html <https://groovy.apache.org/ 
> wiki/GEP-16.html>
> 
> I know we have "final", but many developers I speak to from the Kotlin 
> and Scala worlds are big fans of "val" and believe it was the right name 
> to use for those two languages.
> 
> Given that it involves changes to only about 15 lines of production 
> Groovy code and has well-identified impacts (arguably edge cases with 
> workarounds), I am largely in favor of this proposal, but I am keen to 
> hear other's thoughts.

I must say I agree a lot with OC and mg. I do not see the value of val, 
if it is just an alias for final. And there is the breaking code issue. 
Remember that we have def that kinda works like an alias for Object, 
which already did confuse many people in the past.

But there is also the usage in bodies and the usage for declaring 
properties and fields. (also partially mentioned, just want to extend on 
that discussion)

a) method body

final foo = new Foo()
foo.bar = 10

Dynamic Groovy will  issue a variable with static type Object which gets 
a Foo assigned. foo.bar can be used since the runtime type is Foo and 
the static type plays no role here.
Static Groovy should also issue a variable with static type Object 
afaik.  foo.bar works here because the compiler knows by flow typing 
that foo is actually a Foo and casts foo to a Foo. But since foo will 
not change it is legal to just give foo here the type Foo instead of 
Object and save on the casts. Which is what static Groovy does.


b) property/field
class Foo {
   final bar = new Bar()
}

Here again dynamic Groovy will use Object and so  will static Groovy, 
since formally the type of bar is Object. It is kind of a special case since

class Foo {
   final bar
   {
     bar = new Bar()
   }
}

is not evaluated in Groovy like in Java when it comes to type 
information. In fact, Groovy also accepts this

@CompileStatic
class Foo {
   final bar
   {bar = new Bar()}
   {bar = new Bar()}
}

which should fail compilation since we assign twice to the field bar.

Anyway, point is the property/field type is Object, which may not be 
what you desire.

bye Jochen