
Var and val in Java? - frostmatthew
http://blog.joda.org/2016/03/var-and-val-in-java.html
======
deanCommie
I wish the Java Language committee would stop wasting time and just blatantly
copy C# already. The answer is "var", and it was always var, and it will
always be var. But they're dragging their feet because they want to be
different from C# out of some misplaced spite (Which is how the last debacle
with the lambda notation happened).

Just do what C# did. Then rinse lather and repeat for Generics, Async/Await,
Auto-Properties, and Extension methods. And all the features I don't know
about in C# 6 because I've been stuck in the dreary land of Java since before
that came out.

~~~
kodablah
I disagree. The answer is not just "var" because you have now completely
dismissed local variable immutability (something C# does not have). Did you
read the link you are responding to? I am also not sure why you believe they
want to be different "out of some misplaced spite"...any source for these
claims? Finally, Java needs to be easy to parse and backwards compatible, and
after all it does have many runtimes by other companies. What if I had a class
named "var" (which does happen in auto-generated code)? These things need to
be discussed out in the open (something C# did not do during those older
decisions). As for the other features you mention, there are many reasons why
they are different and many people can argue in favor of Java's approach (e.g.
generic type erasure is backwards compatible as opposed reification,
async/await are library problems not language ones, etc). They are different
languages, they take different approaches to changes, and I believe it is
unfair to hand-wavingly dismiss it as "wasting time".

~~~
dfkf
> The answer is not just "var" because you have now completely dismissed local
> variable immutability (something C# does not have)

It is something that C# does have. It just doesn't allow immutable variables
to be implicitly typed, i.e. you can't write something like "const var x = 0;"
This lack of let or val in C# is a reminder that "var" was introduced in the
language not just to reduce visual clutter, but to support anonymous types,
which were in turn introduced to greatly enhance LINQ experience allowing for
such nifty feature as "let" clauses in query expressions...

------
airless_cotton
One aspect that the author mentions only in passing–but is interesting to look
at in more detail–is to understand how Scala has solved this in a very
consistent and satisfying fashion:

Instead of mixing "you can't override this in a subclass" and "you can't
reassign this value" as Java did with final, it clearly separates these
concerns:

    
    
      class Foo {
              var qux = 1.23
              val bar = 42
        final var fiz = "fiz"
        final val wow = "wow"
      }
      
      (new Foo).qux = 2.34  //   valid
      (new Foo).bar = 23    // invalid
      (new Foo).fiz = "fuz" //   valid
      (new Foo).wow = "wew" // invalid
    
      class SubFoo extends Foo  {
        override var qux = 2.34  //   valid
        override val bar = 23    //   valid
        override var fiz = "fuz" // invalid
        override val wow = "wew" // invalid
      }

~~~
deanCommie
I know C# and Java, but not Scala.

That is NOT at all clear for me. Why is: (new Foo).fiz = "fuz" // valid?

fiz is Final! Why would you be allowed to re-assign a final variable on an
instance??

~~~
bilalq
Final does not mean immutable, but non-overridable through inheritance. The
val keyword is what makes things immutable.

------
kodablah
I believe "var" and "final" is better than "var" and "final var" respectively.
I mentioned this before[0] but was told that a 5 letter word was too much. I
disagree, I use "const" regularly in es6 even though "var" and "let" exist.
Currently "final" is rarely used for local variables and I think this would
encourage its use. Unlike the author, I am excited for local type inference to
remove unnecessary cruft that I don't believe adds too much. Also, for many it
can reduce the amount of imports. I just hope there is never return type
inference.

0 -
[https://news.ycombinator.com/item?id=11261608](https://news.ycombinator.com/item?id=11261608)

------
revelation
Well, I just looked through the authors recent activity on GitHub, and stuff
like this:

> SecurityPositionCalculationFunction function = new
> SecurityPositionCalculationFunction();

is exactly why Java needs var/val/whatever decide already (PICK ONE! DON'T
RUIN THIS JAVA!).

So I'm not sure why he would pick some piece of code that violates the simple
rules the C# team suggests and then burn that strawman with a flash of
gasoline.

~~~
x0x0
His argument hinges on certain language syntax being awkward when mixed with
declaring local variables final, something I've never seen. He asserts it's "a
reasonably common coding standard", but again, I've written a lot of java code
and never seen this in a coding standard. I skimmed projects I use on apache
and don't see it there either. Maybe it's a finance industry thing?

That said, I'm grateful for joda, and Stephen has written a hell of a lot of
(good) java...

~~~
charleslmunger
I like adding final to most of my local variables. I can declare a variable
final, and no matter how complicated the control flow is that assigns its
value, I know the compiler is enforcing that it's only set once. It also
avoids accidental = rather than == bugs.

------
exabrial
Please. No. Java's beauty is that it is explicit, and that greatly reduces
errors. Your IDE takes care of this crap anyway.

~~~
phaed
I never once had a bug resulting from the use of C#'s var in 10 years of dev
work. Not once.

And I disagree with OP's notion that adding var to Java is at the expense of
the reader. There is no expense, var improves code readability dramatically.

These sound like arguments Java devs came up with through cognitive dissonance
to hold on to the notion that Java's language features are superior to C#'s,
they are not.

~~~
exabrial
No, no need for the straw man attack. I don't think they're superior, but
there already is "one way" to do it in Java, and it should stay that way to
avoid creating a mess. Whether or not it is superior is likely a very
subjective debate that I could argue both ways in.

------
mindslight
Type inference is antithetical to the whole ethic of Java, which is to develop
programmers' discipline by making them perform rote tasks commonly done by a
compiler.

It would also harm the professional users, lowering their productivity as
measured in keystrokes/day.

~~~
kuschku
(I accidentally upvoted you, but wish to explain why I wanted to downvote
you):

That’s just an attack that doesn’t really contribute.

Java’s concept is more about backwards compatibility, and compatibility with
generated code.

Which, btw, is why a lot of the tasks that should commonly be done by a
compiler can be done by a compiler in the Java world as well.

Look at what JavaPoet and Lombok can be used for.

~~~
mindslight
Sorry, I carry the mental scars of a victim of the platform. Seeing that this
is still being debated, a _decade_ after Scala, is simultaneously mind
boggling and unsurprising. If a single person takes my comment as a life
preserver rather than an attack, the world will be a better place.

The problem with "code generation", especially IDE-based, is when the
programmer still has to worry about the resulting complexity. _Reading_ code
is harder than writing it, because understanding is what takes the mental
work. So a language should seek to preserve intent and human-meaningful
structure as its primary goal.

I mean, take this idea of a "pattern" that is manually macro^Wexpanded - In
the best case, a later developer reads many lines and immediately recognizes
the single concept. But likely they recognize the general pattern and miss a
slight difference, because the human brain works by glossing over details.

Scala cut through much of the bullshit, and Clojure is a _beautiful_ piece of
work. But the primitive concepts of the underlying platform still remain as a
crooked foundation. They seem fine when you're just reacting to them, as all
programming requires accepting some layer of abstraction. But eventually you
realize you're committed a long series of seemingly reasonable compromises
(dependency on the massively complex JVM, community libraries that embrace
unnecessary complexity, poor startup time, reliance on a single vendor, and
the aforementioned "half-way" abstractions that represent neither your machine
nor a simple high level model) and you snap, seeking out better abstractions
that can be both _relied upon_ and _transparent_ when needed.

But hey, just because _I 've_ been through this doesn't mean you need to take
my comment as sarcastically as I've written it. The same sentiment will
undoubtedly be earnestly expressed by actual Java programmers still stuck in
that tar pit, talking about explicitness, IDE completion, general uniform
verbosity, and simplistic conservatism. And I personally quite like the hope
in the analogy to the seasoned master starting an apprentice off with a
toothbrush to scrub floors, so that their struggle will encourage them to
grow.

~~~
kuschku
You should really check out to projects I mentioned.

In the Java world, we've abandoned IDE autocompletion years ago.

Annotation processors are the magic of the day.

You write an annotation into your class, say @ToString, and a tostring method
is generated during build — it never shows in the code.

In the same way you can use annotations to do compile time dependency
injection resolution, or to do compile time expansion of ORM bindings.

You write just plain Java, add annotations, and everything else is done by the
— expandable — compiler.

~~~
mindslight
I had briefly looked them over. There's always room for incremental progress,
and a Lisp like Clojure even tackles the issue of syntactic transformation in
a mic-dropping fashion. Yet it still can't address other problems I mentioned
with the platform.

In general, none of my objections are insurmountable - any specific issue will
have an obvious solution, as one would expect in a Turing-complete language.
But this is what makes the tar pit so insidious, as you pay the mental
overhead of workarounds every time you need to cross the abstraction barrier.

------
gravypod
I really don't like var/val definition. My issue is that it makes it nearly
impossible for someone who is not familiar to the language or to the code base
to jump in and start fixing.

Could someone please tell me the following: How do I tell the type of x?

    
    
        var x = callSomeRandomFunction()
    

We have to go look in callSomeRandomFunction, don't we? Now how easy will it
be to do that if you have 15 variables and calls to different functions?

How do you know what types are iterable and what types aren't?

What I love about the way explicit definition works is that you are _almost_
guaranteed that in a function you have the type that you are looking for.

If they kill that, they kill one of the greatest parts of Java: the parts that
make it not only easy to write but easy to understand.

~~~
x0x0
Are you seriously arguing we should optimize the java language for people who
aren't familiar with the language?

~~~
gravypod
I'm saying that a language should be easy to understand by anyone.

Hell, I'd have a hard time debugging new code if I saw var x, y, z;

Var means nothing! It has no implicit meaning. It just means whoever wrote the
code was too lazy to write out the type names.

If you agree with that or not, just know that the few seconds it would have
taken you to type out a full type name will probably save someone debugging
your code in the future hours and make it infinity easier for someone who
comes along and needs to start working on your code base.

~~~
deanCommie
Well, lucky for you "var x, y, z" is never going to happen in a statically
typed language.

dynamic, on the other hand....<looks shiftily into C#'s direction>

J/K. I Love dynamics.

~~~
masklinn
> Well, lucky for you "var x, y, z" is never going to happen in a statically
> typed language.

Why not?

    
    
        let (a, b, c);
    

is perfectly valid Rust, it just declares 3 locals a, b and c.

~~~
gravypod
What type are they?

~~~
heinrich5991
Depends on what you assign to these variables.

    
    
        fn main() {
            let (a, b, c);
            a = true;
            b = [1];
            c = "foobar";
        }
    

[https://play.rust-
lang.org/?gist=ebedd0cd5b6707410aff&versio...](https://play.rust-
lang.org/?gist=ebedd0cd5b6707410aff&version=stable)

~~~
gravypod
That's my problem. YOU can't tell. You cannot just look and see what is going
on.

~~~
masklinn
Sure you can, it's pretty clear that a is a boolean, b is an array on the
stack and c is a string. If the code is so complex you can't eyeball a local
scope you probably have bigger problems than whatever the type of the
variables are, and if you get one wrong the compiler will yell at you.

------
amptorn
I don't care what you do or how you define them, don't have both `var` and
`val` in the same language. Way too easy to confuse.

------
merb

        It is the mixture that is all wrong, and it is that mixture that you do not get in Scala or Kotlin.
    

Why don't we get that mixture in Scala? final is a valid keyword there, too.

    
    
        scala> final var x = "y"
        x: String = y
    

This works, even when it's not used. This would be just a matter of time in
Java when nobody will use the `final var`.

------
coltonv
What the hell is this website? I go on and i get 20 popups and alerts about
how I'm the millionth visiter or something. Is it 2007 again?

------
guard-of-terra
I vote for val - immutable reference/value.

Java needs easy syntax for immutable, while having inferred mutable is
questionable.

