Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Var and val in Java? (joda.org)
49 points by frostmatthew on March 26, 2016 | hide | past | favorite | 59 comments


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.


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".


> 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...


`final var` handles the immutability case.

Any of the potential keywords `let`, `val`, `var` could potentially conflict with auto generated code. This would be a breaking change with those generators.


I don't think they can do it with Generics because of an architectural problem. And while var is probably the best approach to having type inference, I don't even think that's a particularly important feature if you're comparing Java to C#. Having async/await and async IO basically be the default as it is in C# now would be huge. Trying to make things asynchronous in most Java web projects is considerably more difficult than it ought to be. Play framework isn't bad, but given that it's a Scala framework, there's a different set of issues when you're trying to use it from Java.


It's a backwards-compatibility problem. I say, make the breaking changes. The Java philosophy is diametrically opposed to this.


well said


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
  }


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??


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


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


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.


Just for context, another piece of Java code the author wrote is a little library called 'joda time'. And then also the standard java.time library.

Does this make him the best Java coder in the world? No, of course not. But it does make me more inclined to listen when he has opinions on what makes good Java.

Do give him some credit as a good Java developer, is my point.


Nope. Just becuase he made a library that eventually got popular and rewritten for JDK 8 doesn't mean he's some kind of authority. Quite opposite actually. This guys is as backwards is it gets. Just read about his ramblings about Scala.


When someone who is accomplished and respected says things I disagree with, the response I try to have is not to respect him less, but to reconsider my own viewpoint. Perhaps their opinion is from experience I don't have yet, or from a perspective I don't share.

In this particular case, I actually disagree with him about var/val- I think they're a great step forward. But that said, I value his differing opinion on the matter, and try hard to really see his point as to why he disagrees. Perhaps in time I'll realize he was right, or perhaps in time he'll realize he was wrong. Or maybe it will be like putting final on every variable declaration- my teammate and I will never see eye to eye on it (so much extra noise for so little gain, imho).


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...


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.


I do this pretty consistently - it avoids a small category of errors: assignment to the wrong variable is less common when there are fewer variables! But I have to agree that it's unusual. I'm always willing to forego this if the team objects to it because I think the advantage is slight.

I'm therefore slightly in favour of the val/var option over "final var" as the former might encourage the immutable by default approach since it requires less typing. I would guess the view would split pretty much exactly like that between those who do and don't currently use final locals by default. Rich bike-shedding lies ahead :)


this line of code isn't bad actually, because IDEs have autocomplete anyway.


It's easy to create. It's verbose and tedious to read


Maybe it's me but after working with Java for a while I don't mind the verbosity of variable declarations especially when looking at someone else's code.

There's obviously plenty of boilerplate in Java that can be rather painful to deal with at times but again I don't mind it when declaring variables.


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.


(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.


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.


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.


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.


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


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.


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.


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.


If var x = "..." makes it difficult to tell what type x is, the problem is first and foremost in whatever "..." is. If it's your code, FIX IT. Rewrite it in such a way that it IS obvious what type x will be. Intermediary variables, helper functions, and good names for both. (just don't make it a comment. Comments are future code liars and you should feel bad if you contribute more code liars to the world of code)

If "..." ISN'T in your control, then...don't use "var".

If you work with other developers that don't understand the above 2, review their code, influence them, convince them. If you work with so many of such people that you cannot convince them of the value of this, go work somewhere else.


If it's your code it should be obvious, but I can't tell you how many times I've looked at code an it hasn't been. You can't just say "fix it" and it will be true.


Realistically though, almost everyone who writes java professionally uses a big honking IDE to do it, because Java is too verbose to explicitly type out without code completion, and that big honking IDE can easily tell you the type of x without you having to open callSomeRandomFunction.


What about when you have an exception thrown in a library you started using. You open up the library on github or whatever code hosting system they use. You see a bunch of var this var that, and you have no idea how to follow through the code yourself.

You have lost a huge debugging technique, using your eyes, for your lack of patients for writing a variable type.


After using var in C# since its inception I personally say this is a non-issue. At worst autocomplete shows the actual type and the available members and usually you just know the types after a few minutes even if you are looking into some unknown code.


I don't see how without an IDE you could do that.

Something doesn't just stop being a problem because an IDE helps you avoid it.

The explicit nature of Java is what makes it great. What you type is what happens.


Why would you write code without an IDE?

And using var doesn't suddenly make things happen randomly, everything is still perfectly well defined, just less verbose. And it is a feature that 99.9 % of the time does what you want, situations in which you want a different type than the inferred one are rare in practice. Actually the only one that I can remember is initializing a variable with some concrete implementation of an interface and desiring the interface type instead of the concrete type. And this one occurs pretty rarely because I think aiming for single assignment is a good thing.


>And it is a feature that 99.9 % of the time does what you want

While typing a variable name explicitly is a feature that 100% of the time does what you want.


That is why you have the choice to be explicit. You choose between shorter and less redundant code and full control over the type of the variable. What is the point of typing out the same type in a single line twice?

  HashMap<String, AtomicReference<Foo>> fooMap = new HashMap<String, AtomicReference<Foo>>();
What is the disadvantage of using var?

  var fooMap = new HashMap<String, AtomicReference<Foo>>();
It's less redundant, easier to read, does not clutter the code and has exactly the same information content. And if you really want the variable to be of type Map<,> nobody stops you.


I don't think you have to type it twice even now, if you specify the type on the left, you can just specify <> on the right. So you can write something like - Map<String, List<Xyz>> foo = new TreeMap<>(); This has been present from Java 7. The reason I like this is that when you are parsing through some library code you can just look at the variable declaration and ignore its initialization to figure out what type it is.


This is an optional feature we're talking about, isn't it? You won't be forced to use it.

It's been in C# for a few versions, and you do find there are places where it always makes sense to use (foreach loops), and there are places where you want to use some judgement. Of course all variables still have a type, it's just not made explicit in the source code, so you can get your IDE to tell you what it is (e.g. by hovering).


If it is made available it will be used. That's kind of a golden rule: build it and they will come.

If this is widely adopted, I'd say that there will be a lot of problems that stem from it. That's why I say this shouldn't be a feature.


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


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.


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.


> 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.


What type are they?


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...


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


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.


Whatever type the compiler infers based on the assignments you make afterwards (and a compilation error if there isn't any/enough information to infer the type).


One wonders how these people were able to learn Java in the first place.


No one is forced to use the new syntax. If you cannot deduce from the function name what the type is don't use var/val (and think hard about that name .. it is probably bad).


The issue is more with "reading code from other people written like that" and less with "understanding your own code".


What are the costs of this?


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.


    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`.


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?


I vote for val - immutable reference/value.

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




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: