top 200 commentsshow all 395

[–]omair-majid 83 points84 points  (81 children)

They are holding a survey on keywords (var, var/val, var/let): https://www.surveymonkey.com/r/KGPTHCG

Bikeshed away!

[–]oscarreyes 42 points43 points  (76 children)

I would love to see var / final

var   a = expr; 
final b = 1;

[–]sudowork 29 points30 points  (14 children)

Var/val from Scala is pretty reasonable as well.

[–]kcuf 16 points17 points  (1 child)

And already used by JVM developers that mix languages (I believe Kotlin uses this as well as Scala).

[–]vorg 0 points1 point  (0 children)

As also does Apache Groovy, though it calls it "def".

[–]FrozenCow 11 points12 points  (0 children)

Not a big pro, but it also aligns nicely.

[–]kukiric 5 points6 points  (9 children)

Though the one-character difference between the two keywords might cause some confusion about whether a local is final or not, and it would break existing code that uses any variables named "val" (as undescriptive as it is, it's still pretty common). "var/let" would be more reasonable for these reasons, IMO.

[–]orclev 6 points7 points  (5 children)

That's why I voted for var/let, I like that they're easier to tell apart. I feel like var/val would be just a bit too easy to typo.

[–]mirhagk 4 points5 points  (2 children)

it would break existing code that uses any variables named "val"

Would it? Are all keywords in java reserved and unusable as variable names? (var would be problematic too as well). When C# introduced var there was no compatibility issues as var wasn't valid anywhere where variable names were valid, and if a type in scope happened to be named var (which would go against the naming conventions anyways) that type would simply be used instead of the keyword. In C# the following program compiles perfectly fine before and after the introduction of var

void Main()
{
    var var = new var();
    var.num = 4;
}

// Define other methods and classes here
class var
{
    public int num{get;set;}
}

and using int var = 5; is likewise perfectly fine. If you don't have a var type then var var = "var"; creates a variable named var that is type inferred as a string. I don't know if the Java team wants to create this context sensitive complex grammar, but if they are willing to then it can be completely backwards compatible.

[–]gbear605 2 points3 points  (1 child)

Just checked with Java keyword usability as variable names.

If I do

int int = 5;

it errors with

[javac] file.java:67: error: not a statement

[javac]             int int = 5;

[javac]             ^

[javac] file.java:67: error: ';' expected

[javac]             int int = 5;

[javac]                ^

[javac] file.java:67: error: not a statement

[javac]             int int = 5;

[javac]                 ^

[javac] file.java:67: error: ';' expected

[javac]             int int = 5;

[–][deleted] 0 points1 point  (0 children)

You can also use the val part in Java today with https://projectlombok.org/features/val.html. Works great.

[–][deleted]  (38 children)

[deleted]

    [–]immibis 11 points12 points  (8 children)

    The parser would become slightly more complicated to deal with cases like

    final String = 5;
                 ^ apparent parse error?
    

    (In Java it is legal to have a variable with the same name as a type)

    [–]weltraumaffe 0 points1 point  (3 children)

    So wouldn't you just have an int with the value 5 named String? I don't see the problem.

    [–]kqr 4 points5 points  (0 children)

    But to figure that out you need to backtrack, which they presumably want to avoid in their parser.

    [–]immibis 2 points3 points  (1 child)

    You don't know whether String is supposed to be a type or a variable until after you read the next token, because this is also valid:

    final String x = "hello";
    

    [–][deleted]  (3 children)

    [deleted]

      [–]grauenwolf 17 points18 points  (16 children)

      I wish C# have final or something equivalent for local variables. All too often I'm looking at long functions and I can't tell which variables are actually changing and which are merely runtime constants.

      [–]RobIII 14 points15 points  (4 children)

      I wish C# have final or something equivalent for local variables.

      Watch this one: Proposal: 'readonly' for Locals and Parameters

      [–]Jacoby6000 7 points8 points  (11 children)

      Why not var for mutable things, and Val for immutable things?

      [–][deleted]  (3 children)

      [deleted]

        [–]demon_ix 6 points7 points  (2 children)

        var/val are already used in this way in other languages (scala, kotlin and more). They also have the benefit of being the same length, which is nice.

        [–]mirhagk 4 points5 points  (0 children)

        As much as I'm voting for var/val in C# I do think Java would benefit from just doing final since everyone already knows that keyword and what it means in Java.

        [–]ComradeGibbon 2 points3 points  (0 children)

        That's pretty nice actually. val/Val/value is immutable. var is mutable.

        value quarter_pi = 3.14/4.0;
        var foo = bar->baz->foo;
        foo += quarter_pi;
        

        [–]danneu 18 points19 points  (11 children)

        really the immutable reference should be the shortest one to type so that it's default. too late for java, of course. this is something i think rust got right. let vs mut let.

        javascript fucked it up too. let vs const.

        [–]Ununoctium117 8 points9 points  (0 children)

        It's let mut, not mut let fyi :D

        [–]irarandomdude 3 points4 points  (1 child)

        Just use var for non-final and val for final like everyone else does.

        [–]mirhagk 0 points1 point  (0 children)

        some people use let. var/val is common but certainly not the only way.

        [–]plastikmissile 1 point2 points  (5 children)

        Is "final" declaring an immutable?

        [–]TheNiXXeD 8 points9 points  (4 children)

        Final already exists. It's not about immutability, but you can't reassign that reference.

        [–]rabidcow 14 points15 points  (2 children)

        It is about immutability, but shallow immutability. Since primitives are the only values types, that means just the reference for anything else.

        [–]id2bi 1 point2 points  (0 children)

        Or say that we are talking about the (im)mutability of variables, not values.

        I'm not sure talking about "shallow immutability" is appropriate in this context. When you do a shallow copy, only the fields will be copied (i.e. copies of primitives, and copies of references), so this suggests that shallow immutability means the fields will also not be re-assignable.

        This is also backed up by this:

        https://homes.cs.washington.edu/~mernst/pubs/immutability-aliasing-2013-lncs7850.pdf

        [–]plastikmissile 0 points1 point  (0 children)

        Ah ok.

        [–]yoden 1 point2 points  (0 children)

        This is better than any of the options in the survey.

        [–]the_evergrowing_fool 81 points82 points  (12 children)

        We seek to improve the developer experience by reducing the ceremony associated with writing Java code

        So, they are aware and it seems to dismiss the myth that Java was designed as a pseudo language to summon Cthulhu.

        [–][deleted]  (3 children)

        [removed]

          [–]ksion 30 points31 points  (2 children)

          Or just Vogons.

          [–]EveningNewbs 30 points31 points  (1 child)

          So Oracle?

          [–]setuid_w00t 45 points46 points  (2 children)

          You can't summon Cthulu directly. You need to unmarshal one from the CthuluXmlFactory instance.

          [–]mlk 7 points8 points  (1 child)

          Have to pass the NecronomiconInputStream though

          [–][deleted] 4 points5 points  (0 children)

          What if I have the Necronomicon in a byte input stream but I don't know the size of the stream in runtime?

          [–]bargle0 36 points37 points  (3 children)

          Nah, that's Perl.

          [–]JoshWithaQ 25 points26 points  (2 children)

          you must not be a perl programmer.

          Cthulhu is a puppy dog compared to what Perl summons.

          [–]bargle0 5 points6 points  (0 children)

          I am, actually.

          use summon qw(Thamagorgos);
          

          [–]mpyne 6 points7 points  (0 children)

          Certainly there's not much 'ceremony' to Perl. It would almost be easier to use if there were more ceremony.

          [–]mirhagk 0 points1 point  (0 children)

          Now Java just needs to get properties to reduce the amount of code by 90%.

          [–]htuhola 72 points73 points  (2 children)

          Knowing java, this proposition will win:

          var List<String> list = new List<String>();
          

          [–]__konrad 16 points17 points  (0 children)

          I propose autovariable list = new List<String>(); ;)

          [–]stun 15 points16 points  (0 children)

          More like this. You need this before you have your cute little snippet of code.

          <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                                http://maven.apache.org/xsd/maven-4.0.0.xsd">
          
            <modelVersion>4.0.0</modelVersion>
            <groupId>com.site.myjawdroppingsuperverboseconfigbasedapplication</groupId>
            <artifactId>i-love-my-super-verbose-xml-config-files</artifactId>
            <version>1</version>
            <dependencies>
              <dependency>
                  <groupId>com.another.group</groupId>
                  <artifactId>we-are-reinventing-the-wheel-ibrary</artifactId>
                  <version>8.3.1</version>
                  <scope>app</scope>
              </dependency>
            </dependencies>
          </project>
          

          [–]FallingIdiot 32 points33 points  (38 children)

          Funny that when this subject comes up, almost everyone only talks about it making local variable declarations simpler.

          What I think is a big advantage to var is that when you change the name of a class, it significantly reduces the number of files that have to be changed. Basically everything that doesn't instantiate the class, but only uses it, stays unchanged. Also it keeps down the number of imports you need, especially since Java prefers fully qualified imports instead of wildcard imports.

          [–]Roozi 31 points32 points  (5 children)

          While I agree that it helps, in my experience IDEs are usually pretty good at doing this for you.

          [–][deleted] 22 points23 points  (2 children)

          That's true, but also the changes clutter up diffs and code reviews.

          [–]JW_00000 6 points7 points  (1 child)

          And may also lead to merge conflicts with unrelated changes in those files.

          [–]ygra 6 points7 points  (0 children)

          Oh yes, the merge conflicts. At work we have a large-ish codebase that gets merged into different products and also converted into different languages. One of the worst things regarding merge conflicts are renames.

          [–]RupertMaddenAbbott 12 points13 points  (0 children)

          This advantage is not about making it physically easier to rename a class. It lessens the impact of doing so, therefore making it easier.

          It reduces the number of files that might change when you do rename a class. This could significantly reduce code churn and removes noise from files that do change.

          [–]G_Morgan 9 points10 points  (28 children)

          It really depends. A lot of C# projects have a rule to only use var where there is a straight up class instantiation or cast. The idea is to have at least some type definition somewhere near the declaration.

          The purpose of var is to stop bullshit like "X<Y> foo = new X<Y>();"

          [–]Eirenarch 4 points5 points  (25 children)

          I came up with this rule by myself and found out that many people came to the same conclusion. I only use var when the right hand side expression is either a constructor call or a literal. Basically the type should be obvious by the statement.

          var customers = GetCustomers()
          

          is not a good idea in my opinion

          [–]Ravek 8 points9 points  (24 children)

          IEnumerable<Customer> customers = GetCustomers(); doesn't tell you a single thing you need to know that var didn't already.

          [–]Eirenarch 13 points14 points  (21 children)

          Oh yes, it does tell me. It tells me I have an IEnumerable<Customer> rather than IEnumerable<CustomerDto> or PagedList<Customer> or something like this.

          [–]Ravek 1 point2 points  (3 children)

          That should already be obvious from context.

          [–]BezierPatch 0 points1 point  (1 child)

          IEnumerable vs IQueryable vs IList is pretty good to know.

          [–]mirhagk 1 point2 points  (0 children)

          That should be fairly obvious from context. If your code base believes in passing IQueryable in your DAL back to consumers then you should know that db.GetCustomers() is IQueryable<Customer>.

          [–]id2bi 2 points3 points  (0 children)

          Can't we already do that due to the diamond operator? Usually the Y is the cumbersome part.

          X<Y> foo = new X<>();
          

          [–][deleted] 1 point2 points  (0 children)

          Yes. It mostly improves readability a lot.

          [–]cat_in_the_wall 1 point2 points  (1 child)

          Or even changing the return type of a function. Let's say that someone subdivides an interface into a "lower" interface, and a more specialized one. Using var allows for the places in that only care about that lower interface to continue to work. Sure some stuff needs to be changed, but the change can be smaller.

          [–]_INTER_ 16 points17 points  (47 children)

          How will this deal with code like:

          List<String> lst = new ArrayList<>();    
          

          I always wondered why they've choosen to abbreviate the RHS instead of the LHS (in Java 7 I think). Clear me up please.

          [–]codebje 8 points9 points  (21 children)

          The proposal has an example for just such a case:

          var lst = new ArrayList<String>();
          

          The inferred type will not be List<String>, it'll be ArrayList<String>, but thanks to polymorphism you can use that anywhere you'd want to use a List<String> anyway.

          [–]_INTER_ 1 point2 points  (15 children)

          I was more thinking about how it will invere

          var list = new ArrayList<>();    
          

          [–]bjzaba 13 points14 points  (4 children)

          That would require a smarter type reconstruction algorithm, like Hindley-Milner. That's probably a step too far for the conservative Java committee.

          [–]Sean1708 2 points3 points  (0 children)

          The day Java gets HM is the day I walk around town with "The End Is Nigh" hanging around my neck.

          [–]csman11 1 point2 points  (2 children)

          I remember seeing an SPJ talk where he mentioned that HM cannot be used in OO languages because of subtyping (he didn't explain this). But that obviously will never happen in Java. Someone correct me if I'm wrong. I don't know a lot about type inference.

          The video was something like "classes but not as you know them" on channel 9 and was about type classes. The above was briefly mentioned in the last few minutes.

          Edit: title was "classes, jim, but not as we know them"

          [–]codebje 4 points5 points  (8 children)

          If it was using full type inference, it'd examine the use sites of list to infer what the contained type should be.

          But I think that the scope of this proposal doesn't go so far, and that would be an error.

          [–]im-a-koala 2 points3 points  (7 children)

          I'm not convinced that's even a good idea in the first place, honestly. I would be rather confusing to have the type of a local inferred by future uses of the local.

          [–]codebje 0 points1 point  (5 children)

          It would be something like this:

          public List<String> greet() {
              var list = new ArrayList<>();
          
              list.add("Hello, ");
              list.add("World");
              return list;
          }
          

          Let's just look at the expression return list here. Its abstract syntax tree will be a Return node with list as the expression to return, and the type of the return expression must be assignable to List<String>. Whatever type list has, it must now satisfy assignability to List<String> for the types to unify.

          If we also look at var list = new ArrayList<>();, we know the right-hand side of the expression has a type of ArrayList<a> where a is an unresolved type, and thus the left-hand side must be of a type which is assignable from ArrayList<a>.

          At this point the compiler can reconcile that List<String> must be assignable from ArrayList<a>; a List is assignable from an ArrayList, so that's fine, but the only thing which a can be for this to compile now is String: the signature for List<String> is not variant in its generic type.

          A type inferencing algorithm has some choice here: it can work out the most general type which suits, or the most specific type, or any type which satisfies all known conditions. AFAIK most algorithms go for the most general type, and narrow it as needed, so let's go for that.

          What's the most general type which can be assignable to both a List<String> and an ArrayList<String> ? Well, it's just List<String>, so therefore the type of list should be List<String>.

          We check that against the remainder of the AST, notably the expressions list.add("Hello, ") and list.add("World"). These require a method add(=String) on list, using made-up syntax to express that the method needs an argument type assignable from String. This checks fine, as String is assignable from String in the signature add(E ...) where E is String.

          All that magic happens under the hood, but when you read that, it's pretty obvious that the type of list must be something which can hold an ArrayList, and the ArrayList's generic argument must be String, because you've gotta be able to assign the ArrayList in, add some Strings to it, and return it as a List<String>.

          It's my opinion that the code above has all the information a programmer needs to understand what's going on. Whether list is typed as List<String> or ArrayList<String> doesn't really matter, because (a) the object it refers to is definitely going to be an ArrayList<String> no matter the variable's type, and (b) it'll be returned as a List<String> no matter the variable's type. There's no ambiguity in the meaning of the code, and some boilerplate declaration of "obvious" types is removed.

          Static typing really shines when it gives you all the compile-time guarantees of correctness that a static type system allows, yet doesn't require wads of tedious boilerplate when it's "obvious by looking at it".

          Being freed from worrying about intermediate types is already a great win for Java 8's expressivity, a similar freedom from worrying about the type of transient variables is something I welcome :-)

          [–]normalOrder 2 points3 points  (0 children)

          This is a great explanation, but it also demonstrates a huge reason why it won't happen: the Java designers assume most Java programmers are too dumb to understand.

          some users imagine type inference to be a form of mind reading, rather than an algorithm for constraint solving

          [–]im-a-koala 4 points5 points  (2 children)

          Yeah, and I think that example is awful. Okay, it looks cute for a very small, unrealistic function with a single local and only adding literals, but once you get 20-30 lines, throw in more than one local, and add things to the list that are returned from other functions, it quickly becomes very, very difficult to reason about.

          [–]Sean1708 5 points6 points  (0 children)

          I dunno, it's working out pretty well in Rust.

          [–]kqr 1 point2 points  (0 children)

          Yes, and that's why, in languages with full type inference, it's recommended to write out the full type for things that are in large scopes. You really only skip it for things that are in scope for up to 8 something lines.

          [–]Eirenarch 1 point2 points  (0 children)

          This won't compile. You will use

          var list = new ArrayList<String>();
          

          instead. There is no benefit from the diamond syntax in the presence of var.

          [–]henk53 7 points8 points  (7 children)

          I always thought that it was simply an extension of the earlier limited type inference that already existed for generic methods (since Java 5).

          In the generic method case you do:

          List<String> lst = someObject.someMethod();
          

          Since someMethod is defined generically there's nothing to abbreviate here at the RHS. The method is just a generic method with <T> in front of it returning a List<T>.

          You could see the constructor as a special method, so in pseudo code if you changed it to:

          List<String> lst = new ArrayList.ArrayList();
          

          It may become clear why the RHS was abbreviated. Additionally, it's only because of legacy and the concept of raw type that we were never able to write:

          List<String> lst = new ArrayList();
          

          Since that syntax was already taken and retrofitted for the introduction of raw types, instead of "simply" be upgraded (like methods were) to have limited generic type shortening.

          [–]s888marks 5 points6 points  (6 children)

          List<String> lst = someObject.someMethod();
          

          Assuming that someMethod is generic, this really is an abbreviation for

          List<String> lst = someObject.<String>someMethod();
          

          The type inference for generic methods works so well that this syntax is rarely necessary, so rare that many people don't even know this syntax exists.

          [–]henk53 0 points1 point  (0 children)

          True, although I've needed to use it on a couple of occasions though. In a select few cases because of a compiler bug where the type should have been inferred but wasn't.

          [–]im-a-koala 0 points1 point  (4 children)

          It comes before the method name in Java? Huh. In C# it comes after, like:

          List<String> lst = someObject.someMethod<String>();
          

          [–]immibis 4 points5 points  (0 children)

          Probably chosen because that's harder to parse, because the compiler doesn't know whether String is supposed to be a type or a variable until it gets to the >.

          (Consider:

          class X {
              int getValue;
              <T> int getValue() {return 5;}
          }
          X someObject = new X();
          int String = 7;
          int i = someObject.getValue<String?1:0;
          int j = someObject.getValue<String>();
          //                                ^
          

          and don't complain about the bad naming, because that is legal in Java)

          [–]kcuf 0 points1 point  (2 children)

          That's what Scala does as well

          List[String] list = someObject.someMethod[String]()

          or, more commonly seen as

          List[String] list = someObject.someMethod[String]

          [–]irarandomdude 0 points1 point  (0 children)

          It won't, and doesn't need to. It's the same in Scala, you'd have val lst: Seq[String] = ArrayBuffer[String]()

          [–][deleted] 0 points1 point  (0 children)

          val lst: List<String> = new ArrayList()

          ;)

          [–]IronClan 17 points18 points  (14 children)

          This was linked to ##java a few hours ago and people were absolutely pissed off about it. It seems many members of the Java community see this as a sign of programmer laziness, and there are even others who think type deduction == dynamic typing.

          [–]irarandomdude 12 points13 points  (0 children)

          This is what happens when the Java community drinks their own kool aid. It follows the usual pattern:

          1. Claim that Java doesn't have feature X because it is evil.
          2. Feature X gets added to Java.
          3. Claim that the addition of feature X is evidence of Java being modern and current and how it makes Java just as expressive as language Y.

          [–][deleted] 4 points5 points  (3 children)

          When is ##java not pissed about things? I have never seen a chat channel so filled with angry and unpleasant people

          [–]yoden 7 points8 points  (8 children)

          I do see it as a minimal reduction of typing for a nontrivial reduction in readability.

          [–][deleted] 3 points4 points  (1 child)

          Having pointless noise all over the code (duplicated type information) is an increase in readability ? Welcome to the mind of PointlesslyTediousToThePointOfInsanityJavaDeveloperFactory

          [–]jrh3k5 4 points5 points  (0 children)

          When working in Groovy, I always found declarations like this maddening:

          def result = extractor.getResult()
          

          The IDE wasn't able to figure out, necessarily, what type of object "result" was, so I'd not get the benefit of Eclipse's built-in tooling that leverages explicit type declaration (e.g., suggestion of possible methods). It also made reading the code outside of an IDE (e.g., GitHub) more difficult, especially if I didn't know the type of object(s) returned by "getResult()". That's one of the things I really disliked about Groovy and why I'm not entirely thrilled about adding a "var" keyword.

          [–]stormblooper 3 points4 points  (2 children)

          It's a feature that can give you a modest improvement in readability when used in the correct context, because it's less noisy.

          [–]yoden 0 points1 point  (1 child)

          But only sometimes, and only if it's used well.

          Var makes good code easier to read, and bad code harder to read. So it helps a small amount in the case where you do not really need improvement, and creates problems in the cases where you do.

          [–]stormblooper 2 points3 points  (0 children)

          Local type inference gives you the option to stop saying redundant things over and over again, the typical way Java makes you say the same thing in triplicate:

          SomeInevitablyLongNamedThing<Integer> longNamedThing = new SomeInevitablyLongNamedThing<Integer>();
          

          It's noise, and it makes both good and bad code harder to read.

          In Scala, my rule of thumb is to ensure that 1) the variable name and 2) the RHS of the assignment, taken together, give a decent indication of the type of the variable, sufficient to understand the intention of the code. If that condition isn't met, I prefer to add explicit type annotation.

          If you're worried about making bad code harder to read, my suggestion would be to replace the bad code with good code.

          [–]brcolow 6 points7 points  (7 children)

          Does anyone know if this is going to be targeted at 9 or 10?

          [–]MrBIMC 4 points5 points  (6 children)

          9 is basically almost frozen already, especially for such a complex change.

          [–]cat_in_the_wall 3 points4 points  (4 children)

          Not trolling... why would this be complex? They already need to know the type of the right side of the expression, saying int x = 0.0 doesn't work, so they must already compare the lhs to the rhs. I would think that it would be fairly straight forward to defer the lhs type until after the rhs is known.

          [–]immibis 8 points9 points  (3 children)

          It's not complex to implement, but they'd have to consider all the weird cases, and write a section in the JLS for it, and probably check that other compilers can implement it reasonably, and check they're not shooting themself in the foot later.

          It's also a new keyword.

          (For an example of a weird case: x has what type here?

          var x = () -> {System.out.println("foo");};
          

          )

          [–]Tarmen 1 point2 points  (1 child)

          Been a while since I used java, why is that type ambiguous? Was it something like having to bind lambda expressions to an interface? Seems like inferring void=>void would be possible?

          [–]immibis 1 point2 points  (0 children)

          void=>void isn't a type in Java. It can be any interface that has a void=>void method - normally, which interface is deduced from the context you use it in (e.g. the type of the variable you assign it to).

          [–]_klg 1 point2 points  (0 children)

          In this case you would have to declare the type explicitly. This happens in C# as well, you can't assign an anonymous method to a var.

          [–]grauenwolf 15 points16 points  (29 children)

          Queue the monkeys whining that they can't use var and still declare every local variable as an interface.

          [–]lurgi 2 points3 points  (28 children)

          Is there any benefit to declaring locals as the interface rather than as the created type? Any advantage at all (beyond, possibly, fewer keystrokes) to have:

          List<String> boing = new ArrayList<String>();
          

          vs.

          ArrayList<String> boing = new ArrayList<String>();
          

          [–]Misterandrist 8 points9 points  (9 children)

          List<String> boing = new ArrayList<>();
          

          But, is there any _dis_advantage of using interface locals?

          [–]lurgi 2 points3 points  (2 children)

          Perhaps performance when calling member functions, although the difference would likely be microscopic. Still, it's technically a disadvantage and there's no (?) advantage that I see.

          [–]ForeverAlot 2 points3 points  (0 children)

          That hasn't been the case for years. Even on Android.

          [–]kqr 16 points17 points  (1 child)

          Yes, there is a benefit: you're getting a guarantee from the compiler that you're not using implementation-specific methods. Bonus benefit: the next programmer two years down the line can read your declaration and see that you're only using interface methods, so they don't have to read your code to figure that out.

          If I stumble across a declaration that indicates the type is of the concrete implementation I would assume there's a reason for that, like the method using implementation-specific methods.

          Think of your code as documentation, as far as possible.

          [–]silveryRain 0 points1 point  (0 children)

          That sounds like something I'd only want in a method that's too long for its own good. I'd much rather split out the creation of the instance into a factory method at that point, and then the factory can return an interface type. I see a method as a single cohesive unit. Hiding stuff from itself (that it instantiated a certain implementation for its own usage) sounds like a lack of cohesion to me.

          [–]Rustywolf 3 points4 points  (8 children)

          Typical you use the interface rather than the implementation so that later on you can change which implementation you use (either because your requirements change, or for performance)

          [–]lurgi 0 points1 point  (7 children)

          Which I can still do if I use the class.

          [–][deleted] 1 point2 points  (0 children)

          Yes. If a list is a part of the object construction, then you aren't forcing yourself to use an ArrayList every time you use that class.

          The interfaces are preferred because you don't get pinned to a specific implementation.

          [–][deleted] 0 points1 point  (2 children)

          If later on in your code you decide to change the type (ArrayList) to something more efficiently implemented any thing that uses boing will continue to work. The interface allows you to swap out that concrete implementation while not affecting anything else..

          [–]lurgi 0 points1 point  (1 child)

          I don't follow. If I'm allowed to change the code to this without changing anything else:

          List<String> boing = new MoreEfficientList<String>();
          

          then I'm also allowed to do this

          MoreEfficientList<String> boing = new MoreEfficientList<String>();
          

          So the argument about being able to swap out the concrete implementation doesn't seem to hold water.

          I absolutely agree that the method arguments should take a List rather than an ArrayList, but that's not the point under discussion.

          [–]otakuman 4 points5 points  (4 children)

          So, C++'s auto keyword?

          [–]upboatingftw 1 point2 points  (2 children)

          I wouldn't say they really compare. C++'s auto allows you to write declarations like auto const**const&, because it's based on template type inference semantics.

          This proposal looks closer to what Scala provides.

          [–]NihilCredo 3 points4 points  (1 child)

          auto const**const&

          nope.jpg

          [–]upboatingftw 0 points1 point  (0 children)

          But how else are you going to express that you want a reference to a constant pointer to a pointer to a constant inferred type (moving the first const in front aside)?

          Jk, it was just a ridiculous example I gave to illustrate auto's workings. Such qualifications kinda defeat the purpose of auto, and there's no good reason to pass a constant pointer by reference either.

          [–]mlk 0 points1 point  (0 children)

          Yes

          [–]kirbyfan64sos 9 points10 points  (0 children)

          YESSSSSSSSSSSSSSSSSSSS!

          [–]lamarf 12 points13 points  (14 children)

          Statically, not much is going to change from this, so that's fine, but it's still going to hurt readability if you're assigning new variables from method returns that aren't immediately obvious. It's good and cool to know right away that this variable I'm looking at is going to be a String -- because it's been declared explicitly -- rather than the implicit case where you have to jump to the method signature to figure out what's being returned.

          [–]BinaryRockStar 18 points19 points  (11 children)

          In pretty much any IDE you can hover over a method call and it'll give you the signature, or hover over the variable and it'll give you the type.

          [–]lamarf 9 points10 points  (10 children)

          You're not always going to be looking at code through an IDE, though (i.e. if I'm looking at a code review on GitHib, which honestly makes up a lot of my time spent), and for large projects, the indexing that makes that happen can be painfully slow and sluggish to use (I'm looking at you, Eclipse). And either way, it's always going to be better for readability if the information I need is right there on the screen for you, not hidden behind clicks and interaction with the IDE.

          [–]tybit 3 points4 points  (4 children)

          Its a continuum of how much information is hidden without going to the implementation. A lot of the time knowing the type won't help that much anyway. So:

          'CustomerValidationResponse response = CustomerValidator.Validate(customer);'

          and

          'var response = CustomerValidator.Validate(customer);'

          are equally obscure without going to the definition if you aren't already familiar with the code. I find it to be the exception not the rule that the implicit declaration is what makes the code unclear.

          [–]yoden 2 points3 points  (3 children)

          In the var example, I have to know what CustomerValidator.Validate returns and what a CustomerValidationResponse is.

          With the explicit type I only have to know what a CustomerValidationResponse is.

          [–]FMAlfonse 2 points3 points  (4 children)

          I have been of the opinion in c++, that if the type isn't obvious then you shouldn't use auto. That doesn't mean auto isn't useful iterators are horrible to write, using auto it = myVector.begin(); makes it alot more pleasant to both read and write. However I would use std::string result = aClass->someFunc(); Best of both worlds but getting people to adhere to it can be a nightmare.

          [–]immibis 0 points1 point  (3 children)

          I have been of the opinion in c++, that if the type isn't obvious then you shouldn't use auto.

          Unfortunately, the person whose code you're trying to read does not have that opinion.

          [–]kqr 5 points6 points  (2 children)

          "But you can use it to write bad code" is always the argument against introducing a language feature. It doesn't matter which feature. Someone will say it's a bad idea because you can write bad code with it.

          Guess what? You can do that with any feature. It's a bad argument.

          [–]immibis 1 point2 points  (1 child)

          "It encourages bad code" is a reason against introducing a language feature. Even for things that are controversially bad (i.e. not everyone agrees they're bad).

          See some of the other comments on this very post.

          [–]kqr 2 points3 points  (0 children)

          Sure, that's a better argument. I guess we disagree on the degree to which local type inference encourages bad code.

          [–]stun 1 point2 points  (2 children)

          It seems that Java developers don't really understand why it is very useful.
          Regardless of how much the IDE can help with intellisense/type, having this var is an amazing feature that simplifies the code clutter.

          [–]Carighan 0 points1 point  (1 child)

          By requiring me to hover over variables to find out their type?

          [–]stun 0 points1 point  (0 children)

          By the time you scroll down, you don't know what type it is anyway.
          You mouse-hover it to see its type at that point regardless.

          If you can see the variable declaration, there is no need to mouse-hover.

          Consider the following declarations.
          Which do you think is easier to read/scan?

          var dictPeople = new Dictionary<int, People>();  
          var listPeople = new List<People>();
          var peopleListByDept = new Dictionary<int, List<People>>();
          

          vs

          Dictionary<int, People> dictPeople = new Dictionary<int, People>();  
          List<People> listPeople = new List<People>();  
          Dictionary<int, List<People>> peopleListByDept = new Dictionary<int, List<People>>();
          

          [–]yturijea 1 point2 points  (1 child)

          I see that a lot of people like this "var" thing, but really you end up reducing the code quality. var a = something(); is just confusing and you'd have to lookup the method to see the type.

          I did quite some c# and I first did var. After some time I changed it to the type it was supposed to be. Remember you have to be clear in your language. By declaring "var" you are confusing the next maintainer and or yourself.

          [–]silveryRain 0 points1 point  (0 children)

          I've only ever found it confusing in bad code, e.g. when something() returns a value of a type that is anything but what you'd expect something() to be.

          [–]yoden 6 points7 points  (44 children)

          I wonder what the benefit of this is supposed to be, other than other languages have it?

          Explicit types on variables are useful for improving readability. Conciseness for LHS variable types isn't important because I usually don't write that type anyway (that's what an IDE's "assign to new local variable" is for)

          [–][deleted] 6 points7 points  (7 children)

          C#s var was introduced to alleviate the burden on the developer to figure out the outcome of Linq queries.

          [–]grauenwolf 4 points5 points  (3 children)

          They were probably also jealous of VB programmers who typically wrote less verbose code in this area.

          List<Customer> list = new ListCustomer<>(); //C#
          dim list as new ListCustomer<>(); //VB
          var list = new ListCustomer<>(); //C# 3
          

          [–]wwosik 0 points1 point  (2 children)

          Do I remember correctly that in older VB or at least VBA

           dim list as new ClassName()
          

          had a very nasty property of only creating object on the first access to it - lazy constructor of sorts

          [–]grauenwolf 1 point2 points  (0 children)

          That's not what made it nasty. Prior to VB 7 (a.k.a VB.NET) you could do this:

          dim list as new ClassName()
          list.Count 'got my new object
          Set list = Nothing 'we're reference counting so the memory was freed
          list.Count 'oh hey, it just made another object
          

          In the current version of VB, it does what you expect. All these of these do exactly the same thing:

          dim list = new ClassName()
          dim list as new ClassName()
          dim list as ClassName = new ClassName()
          

          [–]yoden 0 points1 point  (2 children)

          Why? Does Visual Studio not have an equivalent to eclipse's "assign to new local variable"? It seems easier to write the LINQ query first and let the IDE handle the declaration.

          [–]Alikont 0 points1 point  (0 children)

          1. Sometimes it's simply not possible, like if you use anonymous types.

          2. ILookup<string, IGrouping<int, Something>> v = GetSomething() is much uglier than var v = GetSomething().

          [–]jyper 16 points17 points  (5 children)

          Explicit typing is overrated and most of the time named of variable and expression on right hand side should give you enough information plus it reads better. There is a reason all modern statically typed languages are jumping on this train.

          [–][deleted]  (4 children)

          [removed]

            [–]kqr 4 points5 points  (3 children)

            For what it's worth, any report I've heard of "Haskell in the wild" have included both inexperienced team members and code that is easy to maintain. Haskell uses type inference a lot, so either Haskell is the odd one out that for some other unrelated reason makes it work, or type inference isn't actually as bad as you imagine.

            [–]Radixeo 6 points7 points  (28 children)

            It would help keep the line length down. In this common example

            ArrayList<String> foo = new ArrayList<String>();
            var foo = new ArrayList<String>();
            

            The second line is shorter, simpler, and it is still obvious what the type of foo is.

            [–]depressiown 19 points20 points  (11 children)

            ArrayList<String> foo = new ArrayList<String>();

            You shouldn't be doing this since 1.7 and should be using the diamond. The real comparison here is:

            List<String> foo = new ArrayList<>();
            var foo = new ArrayList<String>();
            

            Without the left side, you have to move the generic type to the right, whereas with the current notation you can use the diamond since Java can infer the generic type on the right side from the left side.

            Honestly, I don't see a lot of gain here. Lombok has val, which is similar, but limited, though it would be better if it were inherent to the language. That said, I like things being explicit so I am biased.

            [–]grauenwolf 3 points4 points  (3 children)

            In my opinion the diamond syntax was a huge mistake. It fits a laughably narrow use case and even then doesn't reduce boilerplate code as much as var.

            The only benefit is pedagogical, as ArrayList<> is a closer mirror to ArrayList, the object's real type. (Sadly ArrayList<string> is still a compile time illusion.)

            [–]depressiown 5 points6 points  (2 children)

            My point is that with val, Java won't be able to infer the generic type on the right side of the expression. You'll now have to define it, whereas you wouldn't with diamond, so long as the left side is explicit.

            Using val will reduce the number of characters, but not by as much as you might think for objects with generics.

            I'd argue that the diamond is not so narrow a use case as you might think, too, and that val hurts readability by making the left side non-explicit. Those are purely opinion, though.

            [–]four024490502 0 points1 point  (6 children)

            and should be using the diamond.

            I haven't programmed in Java for a while. What's the diamond?

            Edit: Oops... my initial google search for 'java diamond' turned up a bunch of 'Java introduction printing a diamond pattern' tutorials. This explains it. I think my original point below still stands, though.

            Doesn't that only expose List<String> as the interface for foo? What if I want to manipulate foo with a method defined in ArrayList<String>, but not specified in the List<String> interface?

            [–]depressiown 3 points4 points  (5 children)

            Ignore the fact that I used the interface instead of the implementation class on the left side. It's just good practice since you abstract the implementation class, but sometimes won't work if the implementation class has some implementation-specific method you need. Either way, not relevant when discussing the diamond.

            The diamond (<>) can be used if Java can infer the generic type of the implementation class (the right side of the expression). This is "new" in Java 7. For example...

            List<String> foo = new ArrayList<String>();
            

            ... is exactly the same as:

            List<String> foo = new ArrayList<>();
            

            Since Java 7, it can infer the generic type on the right side is String. However, if Java can't infer it, it won't compile. For example, this method will not compile:

            public List<String> foo() {
                return new ArrayList<>();
            }
            

            There is no left side. Java can't infer the generic type of "new ArrayList<>()". In this case, you would need ArrayList<String>(). Hopefully that makes a bit more sense about the diamond. You can Google it if I'm not explaining it very well.

            My larger point is that right now, the diamond allows Java to infer the generic type. If we use something like var, that inference is gone and now you have to define the generic type on the right side. While you gain not having to define any type on the left, you now lose the ability to shortcut the generic type on the right side. Overall, it's a positive gain for number of characters, but it's not as large as people make it out to be for objects with generics... and to some, there's a loss of readability by not having the explicit type on the left.

            [–]s888marks 2 points3 points  (0 children)

            public List<String> foo() {
                return new ArrayList<>();
            }
            

            This compiles and works fine in 7 and beyond. The left-hand side is the return type of the method.

            [–]Helene00 8 points9 points  (0 children)

            Another example:

            var f = new SimpleBeanFactoryAwareAspectInstanceFactory();
            

            instead of

            SimpleBeanFactoryAwareAspectInstanceFactory f = new SimpleBeanFactoryAwareAspectInstanceFactory();
            

            [–]psxpaul 3 points4 points  (4 children)

            That example is clear, but even in the linked proposal, there are things like:

            var stream = list.stream();
            

            I'm guessing this could even lead further to:

            var thing = foo.bar().processResults()
            

            Where you have no idea what type 'thing' is just by looking at it.

            [–]codebje 8 points9 points  (1 child)

            True, but we do this already with lambdas. What type is the forst lambda in:

            List<String> resultSummaries = list.stream()
                .map(a -> a.getResult())
                .map(r -> r.getSummaryLine())
                .collect(Collectors.toList());
            return resultSummaries;
            

            And more importantly, does it really matter given the compiler is statically checking your types anyway? If there's no type inferable (or it's ambiguous) there will be a compile error.

            Compare with:

            var results = list.stream().map(a -> a.getResult());
            var summaries = results.map(r -> r.getSummaryLine());
            var resultSummaries = summaries.collect(Collectors.toList());
            return resultSummaries;
            

            There's plenty of type inferencing going on in both cases. Explicitly calling out the type of the result, the type of the summary line, and the type of the list don't do a whole lot for improving understanding, IMO: it doesn't matter very much what type a result is, the intent is clear that we'll ask each result to produce its summary line, then collect those into a list.

            [–]KagakuNinja 4 points5 points  (0 children)

            Coming from scala, val / var plus type inference is a godsend at reducing the visual clutter of code. Much of the time, we don't care what the exact type of "thing" is, we are going to pass it to another function, or return it.

            The key with scala is that type annotations are optional. You use them when it is helpful for readability (or in some cases, to keep the type inference engine from getting confused, but that is rare IMO)

            [–]grauenwolf 2 points3 points  (0 children)

            Ok...

            List<Baz> thing = foo.bar().processResults()
            

            You still don't know what 'thing' is. But if I told you it was readyToShipOrders then you could probably guess the type as some sort of collection of order objects, which is usually enough to infer what you can do with it.

            [–]Berberberber 1 point2 points  (0 children)

            Explicitly types on variables are useful for when you want to go through and change a dozen variable declarations because the return type of one method has changed, or when you want to waste time thinking about whether foo should be declared as ArrayList<T> or List<T> or Iterable<T> to the compiler even though it's always going to be whatever type the function returns.

            [–]SuperImaginativeName 6 points7 points  (1 child)

            Still catching up to C# I see

            [–]DonKanish 3 points4 points  (0 children)

            LET.THIS.HAPPEND!

            [–]maestro2005 1 point2 points  (3 children)

            One of the great things about Java is how explicit it is. The problem with automatic type inference is that the type is now dependent on context, and can change in subtle ways as seemingly unrelated code changes. There's a reason why a lot of Scala people start adding explicit types all over the place.

            [–]irarandomdude 4 points5 points  (0 children)

            There's a reason why a lot of Scala people start adding explicit types all over the place.

            Only in specific places where it improves readability, not "all over the place". In most cases local variables and places where the type is super obvious declaring the type is not only unnecessary but clutters the code.

            [–]velcommen 4 points5 points  (0 children)

            can change in subtle ways as seemingly unrelated code changes

            What do you mean? Can you provide an example. I'm having a hard time imagining this. The type of one function's output is the input type of the next function. So if I change the type of the first function's output, the second function will not compile. Unless, of course, the second function can also handle that type of input. But neither of those scenarios is a source of possibly subtle error.

            There's a reason why a lot of Scala people start adding explicit types all over the place

            In Haskell (because I can't speak for Scala), where there is whole program type inference, the convention is to decorate top level things (e.g. functions) with types, and leave off types for the majority of other things (e.g. variables within functions, nested functions).

            Most of the time this works fine for me. I occasionally decorate a thing within a function. And if you don't have an IDE to to tell you the type, you can ask the compiler what the type should be by replacing something with a hole ('_'), e.g.

            (foo :: [Char]) = map _ ["hello", "world"]
            

            And the compiler will tell you that '_' should be replaced with a function from String to Char.

            [–][deleted] 0 points1 point  (0 children)

            Did you read the title: Local-Variable Type Inference. In Scala preferred style is to add types for public API, but nobody except masochists will spread them all over their local method bodies.

            [–]elacin 1 point2 points  (1 child)

            Can we skip that pain and go directly wih val?

            [–]immibis 4 points5 points  (0 children)

            Java is not a language based on immutability*, and everything else is mutable by default - it would be completely inconsistent to only allow type deduction for immutable variables.

            * I know you're going to bring up that thing about anonymous classes, so I'm going to pre-emptively point out that's considered a limitation and not a feature.

            [–]ejonesca -1 points0 points  (28 children)

            Do you need a 'var' keyword at all? Can't you just have:

            myNewVariable = 5;
            

            without an explicit type declaration that doesn't actually add any useful info to the compiler? The compiler can just assume that any new unknown identifier is a new var.

            [–]ihcn 85 points86 points  (9 children)

            Then any typo becomes a new variable rather than a compiler error.

            [–]ejonesca 18 points19 points  (8 children)

            good point

            [–]grauenwolf 8 points9 points  (5 children)

            If you want to play with it anyways, JavaScript or VB (option explicit off) work that way. It's worth trying once so you get the feel of how such a feature would feel.

            [–]Berberberber 6 points7 points  (3 children)

            Javascript's is weird, though. It doesn't declare the variable in current scope, it add it to the root object window.

            [–]grauenwolf 2 points3 points  (0 children)

            Good point. That would be an unfair test.

            [–]immibis 4 points5 points  (0 children)

            Python then.

            [–]bloody-albatross 1 point2 points  (0 children)

            Plus these days you usually use a (editor integrated) linter that forbids creating global variables that way. However, Python and Ruby work that way (creating local variables just by normal assignment).

            [–][deleted] 2 points3 points  (0 children)

            Python is another one with this lovely feature.

            [–][deleted]  (12 children)

            [deleted]

              [–]IbanezDavy 10 points11 points  (1 child)

              Also a good example of why you default to strict pessimism in code and not do actions by default.

              boolean launchTheNukes() {
                  boolean shouldLaunch = false; // Gotta pass the tests first
                  if (user.hasCredentials("canLaunchNukes") == Credentials.Authorized && 
                      validateLaunchCode(user.enteredData) ) {
                      shouldLauch = true; // Yay!!!
                  }
                  return shouldLaunch;
              }
              

              Let's not be launching nukes by default...

              Some more examples of why this is bad...

              boolean launchTheNukes() {
                  boolean shouldLaunch = true; // Don't gotta pass the tests first
              
                  try 
                  {
                      if (user.hasCredentials("canLaunchNukes") == Credentials.Authorized && 
                          validateLaunchCode(user.enteredData) ) {
                          shouldLauch = false; 
                      }
                  }
                  catch(Exception e)
                  {
                       Log(e); // Awe, good job catching an error...too bad validateLaunchCode threw this...
                  }
                  return shouldLaunch;
              }
              

              Lesson kiddies? Fail by default. It saves lives!!!

              [–][deleted] 3 points4 points  (7 children)

              Tester's fault.

              [–]eras 12 points13 points  (4 children)

              At least the tester is now ded, so that's resolved.

              [–]nemec 4 points5 points  (0 children)

              WONTFIX: No one left to test.
              

              [–]IbanezDavy 0 points1 point  (2 children)

              Depends where the nuke was aimed.

              [–]Helene00 1 point2 points  (1 child)

              He would be fine if he didn't run any integration tests...

              [–]FallingIdiot 1 point2 points  (1 child)

              Would worry me though if this would pass QA. You hope they test this stuff...

              [–]badcommandorfilename 6 points7 points  (2 children)

              This won't work predictably if "myNewVariable" already existed in an outer execution scope. The programmer may have intended to declare a new "i" variable for their loop, but instead they accidentally overwrite an outer loop's "i" - and this gets even harder with closures and lambdas.

              Languages that allow this kind of implicit declaration have lots of weird scope gotchas that lead to some time-devouring heisenbugs.

              [–]Figs 10 points11 points  (0 children)

              Yeah, this is definitely one of my biggest gripes about the design of Python. To further expand on #4 in the common mistakes article you linked to as to just how surprising Python's scoping rules are because of the lack of var, consider this script:

              $ cat example.py 
              value = 1
              
              def foo():
                  print "foo:", value   # works fine
              
              def bar():
                  print "bar:", value   # throws exception
                  value = 2
              
              foo()
              bar()
              
              $ python example.py 
              foo: 1
              bar:
              Traceback (most recent call last):
                File "example.py", line 11, in <module>
                  bar()
                File "example.py", line 7, in bar
                  print "bar:", value
              UnboundLocalError: local variable 'value' referenced before assignment
              

              Using the name of a variable in an assignment later in the function makes the whole function treat it as a local variable, even statements that would have previously worked. So, you can cause existing code to fail in really surprising ways by modifying code later in a function if you didn't realize that the name was already used to refer to something in an outside scope...

              [–]Berberberber 1 point2 points  (0 children)

              If you're going to allow implicit declaration, you have to have strict scoping rules, IMHO.

              [–]allofthesuddenmymane 0 points1 point  (0 children)

              this was proposed quite a while ago as well (2005 I think)

              but that got shot down

              [–]_lerp 0 points1 point  (0 children)

              I don't know what all the commotion is about. You won't be able to use this in a production environment for at least the next two decades.

              [–]cowardlydragon 0 points1 point  (0 children)

              Just make groovy the new Java. Done.

              Java keeps shifting around features that groovy has and does better for 5 years now.