48

Java 10 brings a C#-like var keyword for local type-inference.

But does Java 10 also provide a val keyword, as is found in Scala?

val would work like var but the binding would be final.

var x = "Hello, world. ";
x = "abc"; // allowed

val y = "Hello, world. ";
y = "abc"; // forbidden

If it does not, is there a reason that this is the case?

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
  • 1
    Not sure a "yes/no" question would be a good question here. But I don't see why it would include both `var` and `val` for the "same feature". – AxelH Mar 22 '18 at 11:03
  • Probably not: https://blog.codefx.org/java/java-10-var-type-inference/#Why-Is-There-No-valconstlet So, it'll be `final var` – Thilo Mar 22 '18 at 11:05
  • @AxelH `val` and `var` have different meanings, so they are not the same feature – sdgfsdh Mar 22 '18 at 11:06
  • 1
    Both do type-inference, one is final, the other is not. This is what I call the same. Is `String` and `final String` are different type for you ? – AxelH Mar 22 '18 at 11:06
  • In the case of `String` then `var` is equivalent to `String` and `val` would be equivalent to `final String`. They are related, but not the same. – sdgfsdh Mar 22 '18 at 11:07
  • 2
    Did you ***[try it out](https://tio.run/##y0osS9TNSsn@/7@gNCknM1khOSexuFjBNzEzT6GaixMqWFySWAKkyvIzUxRygVIawSVFmXnp0bEKiUXpxZoglZzBlcUlqbl6@aUlegVAyZKcPA0lj9ScnHwdhfD8opwURSVNay7OWq7a//8B)?*** – Naman Mar 22 '18 at 11:31
  • I think this question can be salvaged by turning this into a "why" question instead of "yes/no" (the accepted answer remains valid). – Pixel Elephant Mar 22 '18 at 18:43
  • @PixelElephant fair point; question updated – sdgfsdh Mar 23 '18 at 10:34
  • @sdgfsdh Why not you try Kotlin code in your java project. Kotlin provides `val` keyword. You can use Kotlin in Java code and vice versa. You can find the sample code used [here](https://webfirmframework.github.io) which uses `val` keyword. – RRadley Dec 27 '18 at 04:52
  • Side note, if you still want to use val anyway, you can always use Lombok – Rik Schaaf Feb 09 '22 at 20:27

3 Answers3

56

There is no val in Java 10, as stated in JEP 286: Local-Variable Type Inference:

Syntax Choices

There was a diversity of opinions on syntax. The two main degrees of freedom here are what keywords to use (var, auto, etc), and whether to have a separate new form for immutable locals (val, let). We considered the following syntactic options:

  • var x = expr only (like C#)
  • var, plus val for immutable locals (like Scala, Kotlin)
  • var, plus let for immutable locals (like Swift)
  • auto x = expr (like C++)
  • const x = expr (already a reserved word)
  • final x = expr (already a reserved word)
  • let x = expr
  • def x = expr (like Groovy)
  • x := expr (like Go)

After gathering substantial input, var was clearly preferred over the Groovy, C++, or Go approaches. There was a substantial diversity of opinion over a second syntactic form for immutable locals (val, let); this would be a tradeoff of additional ceremony for additional capture of design intent. In the end, we chose to support only var. Some details on the rationale can be found here.

And here's the main reasoning:

I know this is the part people really care about :) After considering the pros and cons at length, there appears to be an obvious winner -- var-only. Reasons for this include:

  • While it was not the most popular choice in the survey, it was clearly the choice that the most people were OK with. Many hated var/val; others hated var/let. Almost no one hated var-only.

  • Experience with C# -- which has var only -- has shown that this is a reasonable solution in Java-like languages. There is no groundswell of demand for "val" in C#.

  • The desire to reduce the ceremony of immutability is certainly well-taken, but in this case is pushing on the wrong end of the lever. Where we need help for immutability is with fields, not with locals. But var/val doesn't apply to fields, and it almost certainly never will.

  • If the incremental overhead of getting mutability control over that of type inference were zero, there might be a stronger case, but it was clear that many people found two different leading keywords to be a distraction that kept their eyes from quickly settling on the important stuff. If variable names are more important than types, they're more important than mutability modifiers too.

(Source)

Antony Stubbs
  • 13,161
  • 5
  • 35
  • 39
Eran
  • 387,369
  • 54
  • 702
  • 768
  • 7
    "_[..] Some details on the rationale can be found [here](http://mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-December/000066.html)_" – AxelH Mar 22 '18 at 11:24
  • 7
    "_Immutability is important, but in reality, local variables are the least important place where we need more help making things immutable. Local variables are immune to data races; most locals are effectively final anyway. Where we need more help in encouraging immutability is *fields* -- but applying type inference there would be foolish._" – AxelH Mar 22 '18 at 11:30
  • 2
    Interesting, is it possible to enhance final for this approaches? Namely, to support usage like this: final varName = new Object(). Isn't it logical that if you put final inside methods then you mean final var? Just, maybe silly, fantasy. – ekar Apr 09 '20 at 09:00
  • 3
    @Eran I think it was definitely overlooked that there's WAY less cases where we want variables compared to constants in most programs. It would have been much more beneficial to support `val` over `var` IMO and people would also stop declaring variables where constants would suffice... – plalx Dec 31 '20 at 03:02
  • 9
    For example, since JavaScript added `const`, almost no one uses `let` unless required. Furthermore, the argument that 2 keywords would be too distracting is absurd. They could read through all these explicit type declarations and suddently they would get too distracted by `var/val` or `var/let` to understand the code? To better support mutability over immutability is as absurd as allowing references to be `null` by default... – plalx Dec 31 '20 at 03:18
11

Because there is final var for that in Java. If we had val too, there would be two things that mean the same. This is not good. There should be only one way to express a particular thing.

ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155
  • 32
    `var` also does not seem to express anything that was not possible before. Both `var` and `val` just make things shorter. – Michal M Nov 15 '18 at 10:04
  • 5
    `var` does express something that was impossible before: the real type of an anonymous class. For example, it's now possible to do `var foo = new Object() { int i = 1; };` and access `foo.i` _without reflection_. Of course, this is only useful within the body of a method, since you can only return the supertype. – Micheal Hill Feb 24 '20 at 21:26
  • 1
    @MichealHill Actually it was possible before. E.g. you can write `t(new Object() { int i = 1; }).i` in Java 8, where `t` is defined as `public static T t(T t) { return t; }`. – ZhekaKozlov Feb 25 '20 at 07:54
  • 9
    This is a highly opinionated answer with no clear basis. There are lots of ways to express a loop: `for(;;)`, `for (x : y)`, `.forEach`, `do..while`... – Lucas Ross Jun 18 '20 at 16:00
  • @LucasRoss These are quite different flavors of a `for` loop. – ZhekaKozlov Oct 13 '21 at 09:24
  • an if statement and a switch statement can also express the exact same thing, but having both gives the flexibility to write clearer and terser code. val would also help with that. – Rik Schaaf Feb 09 '22 at 20:34
  • @ZhekaKozlov what's the advantage of `t(new Object() { int i = 1; }).i` over `(new Object() { int i = 1; }).i`? – Ricola Mar 30 '23 at 11:54
  • There's alway Lombok for someone who disagree. Lombok val takes Java closer to Kotlin and allows to leverage legacy code base but modernise it for better readability, safety, and semi-forma proof of execution path. – PranasB Aug 01 '23 at 00:07
10

If you want to use "val", that is, "final var", you always can to use Lombok's val.

Alberthoven
  • 2,798
  • 1
  • 24
  • 29