Type Inference: Another Bad Idea for Java 7

Peter von der Ahé and a few others are pushing type inference in Java 7. The goal is to not have to explicitly declare local variable types. Remi Forax offers this example:

  // print a frequency table of words
  public static void main(String[] args) {
    map := new HashMap<String, Integer>();
    for(word : args) {
      freq := map.get(word);
      map.put(word, (freq==null) ? 1 : freq+1);
    }
    System.out.println(map);
  }

Peter von der Ahe and Christian Plesner Hansen suggest reusing the final keyword instead:

  public static void main(String[] args) {
    final map = new HashMap<String, Integer>();
    for(final word : args) {
      final freq=map.get(word);
      map.put(word, (freq==null) ? 1 : freq+1);
    }
    System.out.println(map);
  }

Note that both proposals have the side effect of making the local variable final, as well as inferring its type, although it’s more explicit in the Ahé proposal.

Type inference actually makes some sense in languages like JavaScript and PHP that are built around this, and had this feature from day 1. It makes no sense in a language like Java that’s built around the opposite. It makes Java look weakly typed, but it isn’t. In fact, if anything this is now more strongly typed because, for example, you have to type a Map variable as a HashMap or a TreeMap rather than just a Map. That is,

map := new HashMap();

is equivalent to

HashMap map = new HashMap();

not

Map m = new HashMap();

Much more importantly, though, it’s more syntax that makes the language larger and harder to learn. I used to be able to teach pretty much all the important parts of Java in one semester. Now I can’t even think about doing generics, annotations, and enums unless I drop GUIs. Java 1.0 was designed as a good teaching language. Java 1.1 was pretty good too. Every piece added to it since then—anonymous inner classes, strictfp, closures, enhanced for loop, generics, type inference, etc.—made it less suitable for that purpose.

Even if I try to teach type inference, I have to cover a lot of special cases, and explain what it means to make a local variable final first, and why you might want to do that. This makes some sense to those of us who’ve been breathing this stuff for 10+ years now. It makes no sense at all to anyone who’s coming to the language for the first time. It’s just one more source of weird, incomprehensible compiler error messages they have to ask their professor to debug for them. Is this really worth saving a few keystrokes of typing?

It’s time to call a halt to new features in the Java language. I am not saying that the features are wrong, just that they don’t fit into the language any more. It’s already too bloated. I am not saying that generics, type inference, closures, compiler created factory methods, and other kitchen sink proposals are bad. They’re not. I am saying that they simply don’t fit into or with the current core language, and every one we add makes the language worse, not better.

If these features are necessary, and some of them may be, then they should be designed into a new language from the beginning. This new language could have real generics without type erasure. It could have := but not =. It could have factory methods and not have constructors. It could have closures and not have anonymous inner classes. That would be a language that made sense, and that you could still teach in one semester without tripping over 37 different special cases.

However the current push to add new language features to Java without taking anything away must stop. Every single one makes the language worse, not better. Every single one makes Ruby and C# and Python look more attractive. You cannot build on top of an old foundation forever. Fifty story skyscrapers cannot be built by adding floors to a five-story tenement. Sometimes you have to move down the block and start building in a new lot. For Java, that time has come.

61 Responses to “Type Inference: Another Bad Idea for Java 7”

  1. Reg Braithwaite Says:

    Hear hear!

    Adding new features only works if you are able to deprecate features at the same time. There are many reasons why deprecating features is hard. And as you point out, good reasons why adding new features is a bad idea.

    Java’s original goal was to suck the oxygen out of MSFT’s monopoly on APIs for desktop and server development. This goal has been admirably reached. Now to continue that mission, does Sun need java to be all things to all people? I think not, it is sufficient that the JVM be pervasive.

    So why not encourage new languages on the JVM? As you point out, this would make better languages while keeping Java good at what it does, good for what it is today.

    This is why I’m a supporter of JRuby, Groovy, Nice, and other efforts. Everybody wins when there is a family of languages that interoperate with the JVM ecosystem and libraries.

  2. Stefan Schulz Says:

    I think you are wrong with Peter promoting type inference the way you wrote. His proposal, and what would come useful, is on static factory methods that infer generic types on the RHS. The interview you cited actually refers to exactly this proposal.
    Generally, type inference as you describe it being proposed is a feature that rather belongs to weakly typed languages and it would be no good idea to have it in Java. Type explicitness is one of the things I like in Java, and inferencing “only” saves you some keystrokes. Yes, it somewhat follows the DRY principle, but it actually does not in many cases, where you have a different LHS type (interface, superclass) to the RHS (class).

  3. Cay Horstmann Says:

    Have you looked at C# lately?

  4. Masklinn Says:

    It makes Java look weakly typed, but it isn’t.

    I don’t see how it does that, it makes Java look less verbose but that’s pretty much it (for the second proposal at least, the first should use a defined keyword such as the good ol’ let). Many statically, strongly typed languages are also type inferred, and it doesn’t in any way make them look weakly typed.

    In fact, if anything this is now more strongly typed because, for example, you have to type a Map variable as a HashMap or a TreeMap rather than just a Map. That is,

    map := new HashMap();

    is equivalent to

    HashMap map = new HashMap();

    not

    Map m = new HashMap();

    It doesn’t in any way have to be like that. A good type inference system is perfectly able to use interfaces (e.g. Haskell’s type inference systems have no problem inferring to typeclasses instead of “concrete” types). The type inferer (and therefore the compiler) requires much work, but is much more intelligent in the end. Sounds like a good thing to me.
    So there’s no actual reason (apart from lazyness of the implementors) for a Java type inference system not to be able to infer to interfaces.
    About the last two paragraphs, I completely agree, but do you think Sun would deprecate (or start deprecating) Java anytime soon to replace it by another (arguably better) language such as Scala or Nice (or derived, even more java-like languages)? This is probably the best thing that could happen to the JVM and JVM-based languages, but I don’t see it happening.

  5. Elliotte Rusty Harold Says:

    No, you really can’t infer the interface here. It pretty much has to be the concrete class. Consider

    f := new Foo();

    where

    class Foo implements Bar, Baz

    There are three possible types one could infer for f: Foo, Bar, and Baz. Foo can server as a Bar or Baz as necessary, but the reverse is not true. Thus the concrete class Foo is the only reasonable one to pick. In a more dynamically typed language, the type doesn’t need to be inferred at all. However Java is not such a language.

  6. Masklinn Says:

    Thus the concrete class Foo is the only reasonable one to pick.

    Of course not, there’s a whole lot of context which you fail to take in account, and this context creates a great number of clues and informations that allow the compiler (and the type inferrer) to determine the fittest (and most abstract possible) type for your data.

    In a more dynamically typed language, the type doesn’t need to be inferred at all. However Java is not such a language.

    Harold, please be serious for a second. I already cited Haskell, I can add SML and OCaml if you wish, I hope you’re not telling me that these languages are somehow more dynamically typed than Java, that would be a travesty. Yet they all feature very well built type inference systems which do exactly what you consider “impossible to do”.

  7. Bruce Eckel Says:

    Spot on. The JVM is the true “big step forward” that Java has contributed to the world of computing, and the ability to build new languages on top of a system that already has a garbage collector, exceptions and hotspot. That foundation will allow new languages like Scala to rocket into existence without the interminable wait for implementation that past languages have suffered. But continuing to try to retrofit Java to play catch-up with C# (which is seriously moving forward with some amazing features, a fact that most in the Java community don’t seem to be noticing) and Ruby (the closures proposals are already looking like the next generics, sigh) just makes it look bad. As you say, it’s not the features that are bad, it’s the implementation that comes from shoehorning them into a language set in concrete. Personally, I think Scala might be the next step up; everything looks like it’s at a higher level of abstraction, and it makes Java look like souped-up C by comparison.

  8. Robert Says:

    >> You cannot build on top of an old foundation forever. Fifty story skyscrapers cannot be built by adding floors to a five-story tenement. Sometimes you have to move down the block and start building in a new lot. For Java, that time has come.

    Another opportunity to point out that ‘Enterprise java’ along with ‘SOA’ are just examples of corporate PHBs recycling COBOL/VSAM code and architecture into another language. Bruce Tate said that a while back, too. These folks are still running 1.22 and 1.3.1, and treating everything that gets written as if it were carved in stone. Thus ‘SOA’; “leverage legacy code”. More so each day, that legacy code is java emulating COBOL; which is what it was when it was written. It really is time to move on.

  9. Paul Prescod Says:

    You say: Type inference actually makes some sense in languages like JavaScript and PHP that are built around this, and had this feature from day 1.

    Actually, neither mainstream JavaScript nor PHP have type inference. I think you’re looking for ML and Haskell….and by the way, those languages are more strongly typed than Java. It is a lot harder to work around the static type checker by casting in those languages.

  10. Ricky Clarkson Says:

    The specific issue that brings type inference up is repetitive type parameters. For example:

    Map<String,String> map=new HashMap<String,String>();

    This can be solved in one of two ways, with no actual language change:

    1. Map<String,String> map=hashMap(); //where hashMap is a static utility method. There already is some inference in the compiler that makes this possible.
    2. Map<String,String> map=new HashMap(); //look, ma, no type parameters on the rhs. This is already valid syntax, but gives a warning. Perhaps that warning could be disabled.
    As for adding type inference in general, it’s a good thing. If you don’t want to use ArrayList’s methods, you don’t have to. Also, if you really have a problem with being able to use them, then make an arrayList() method that returns a List, and do: final list=arrayList();
    There’s nothing conceptually hard about interfaces here, except that at some point it became unfashionable to write code that uses concrete types, even when it actually instantiates those types there and then.

  11. Masklinn Says:

    Paul Prescod Says:
    It is a lot harder to work around the static type checker by casting in those languages.

    Is it even possible to cast in these languages? I don’t remember seeing any possibility to cast in Haskell, even the addition of an integer and a float requires an explicit conversion of the interger to a float.

  12. Impatient Says:

    What’s the difference between Java adding new features and C# adding more features? If Java trying to catch up to C# is a bad idea, then why are all the new C# features a good idea? Honestly wondering, here.

  13. Masklinn Says:

    What’s the difference between Java adding new features and C# adding more features?

    I guess part of the issue is that C# seems “young” and “ever-changing” while Java is old and its user are encrusted in their habits which they don’t really want to change.
    Also C# has F#, Cw and Microsoft Research doing CS research before they introduce new features in the language, while I don’t see anything else than Fortress in the Sun Labs language researches. Now Fortress is (probably) a very good language, but it doesn’t really help Java more forward in the direction C# moves to.

  14. albert bulawa Says:

    I think the real problem with type inference is that it hides the programmer’s intention (I want to see explicitly whether it is meant to be a TreeMap, a SortedMap or just a map? Can I safely replace it with MySuperCowMap?). The compiler will probably be smart enough to infer types and maybe even find the correct interface but I cannot. So it really really hurts maintainability of the code.

  15. Stefan Tilkov Says:

    Type inference has nothing to do with weak typing, only with removing unnecessary syntactical clutter — which is a very good motivation for adding something to the language. In this particular case, adding something to the language means I can actually remove something from my code (which is good).

    I’m not going to argue whether one or the other detailed proposal is better, but no one can convince me that needing to type something like

    MyCollection<MyItemType<MyNestedType>> col = new MyCollection<MyItemType<MyNestedType>>();

    is better than

    col := new MyCollection<MyItemType<MyNestedType>>();

  16. Pete Kirkham Says:

    Consider
    f := new Foo();
    where
    class Foo implements Bar, Baz
    There are three possible types one could infer for f: Foo, Bar, and Baz.

    You could also infer the type which is the union of Bar and Baz, if your type system supports unions, which many inferencing systems do.
    Do you have an opinion on Fortress? It has the features you describe as a language which makes sense, though I’m not sure it’s simple enough with its desire to express all the features of operators and numeric types as groups, rings and fields.

  17. Ben Says:

    I thought Java was designed as a language for Toasters, not as a teaching language…

    Anyway – I care for more about how much more readable and expressive new language features would be than whether they could be taught in a 1 semester course.

  18. galo Says:

    java isnt a testbed for new technologies, or some highly modular language that allows you to redefine syntax and make things easier as you add features and more features. its quite the opposite. That is why, as you put, type inference is a bad idea, and why closures will probably be a bad idea (unless very well implemented) and why other features from “new” languages wont be as nice and simple.

    Java is and elephant that can walk around the world. But can do it only by one route.

  19. Augusto Says:

    Impatient;
    “> What’s the difference between Java adding new features and C# adding more features? If Java trying to catch up to C# is a bad idea, then why are all the new C# features a good idea? Honestly wondering, here.”

    I’m wondering the same thing, why does Java have to remain static while other languages can keep “evolving” specially Java clones like C#.

    Bruce Eckel;
    “>But continuing to try to retrofit Java to play catch-up with C# (which is seriously moving forward with some amazing features, a fact that most in the Java community don’t seem to be noticing)”

    Again, why can C# get new language features and Java can’t? What about actionscript 3 (http://www.adobe.com/devnet/actionscript/articles/actionscript3_overview.html), do you think adding new language features to that is bad too?

    Hey, I’m all for changing languages when it makes sense, but it’s a hard argument to make that because you want generics you have to move all your tools, platforms, and retrain everybody just for a set of language features. That is, in the *real* world.

    BTW I do agree, this proposal is *horrible* … I don’t get what it’s trying to solve … but I’m not reflexively against new language features, if they make sense.

  20. struberg Says:

    > Type inference has nothing to do with weak typing, only with removing unnecessary syntactical clutter

    But if removing the need to type a few characters more is the only argument to redesign a language, then i would prefer to leave it as it is.
    Design ‘beautification’ changes with only a very limited benefit (compared to e.g. templates/generics) should imho be omited completely, since this leads to many different ways to code the same thing.

    For me, this is currently one of the big advantages of Java: the syntax is clear and almost everyone could read it.
    If Sun is adding more flavors to write things, this benefit will get lost sooner or later.

  21. Cormac Says:

    I actually think C# is going to be damaged by all the new features being added in. Guys writing backing classes for ASP.NET pages are not going to get them.

    I wish Nice was more actively developed. Reading the Scala docs makes my head hurt :)

  22. Jeremy Weiskotten Says:

    I’m not sure why it matters if f = new Foo() // where Foo implements Bar, Baz implicitly types f to Foo, and doesn’t type it to one of its interfaces. Object f can still be passed to any method that expects a Bar or a Baz, or a Foo, because it is all of those things. Figuring out (based on context) that it can be typed to Bar or Baz doesn’t add any value that I can see. This doesn’t prevent you from “programming to interfaces” (which I’m all for for the usual reasons).

    Please correct me if I’m wrong!

  23. Jochen Bedersdorfer Says:

    Are we really discussing Ctrl+1 here?

    I rarely, if ever physically write code like this:
    Map<A,B> map = new HashMap<A,B>();

    instead I type:
    new HashMap<A,B>(); and press Ctrl+1 in Eclipse.
    Eclipse even lets me choose the interface/class I want for my variable.

    It saves typing the type info and is much less error-prone!
    We are not creating Java classes with emacs anymore, folks.

    The proposed syntax does NOTHING for readability and – with a decent editor – nothing for
    “writeability”.
    In fact you could argue that readibility is decreased!
    myVar := getMap();

    is less obvious than
    Map<String, Person> myVar = getMap();

    Cheers,
    Jochen

  24. Alexander Fairley Says:

    This comment right here says everything about why this feature should not be added:

    “His proposal, and what would come useful, is on static factory methods that infer generic types on the RHS”

    The jargon to meaning ratio of that sentence is ridiculously high, and that is essentially what is wrong with the entire Java language.

  25. Ravi Venkataraman Says:

    Jochen, Is Java without Eclipse (or some IDE) not Java any more? If one **must** use an IDE to handle the verbosity of the language, that speaks volumes about the language.

  26. Pinner Blinn Says:

    I’m totally with Rusty on this one.

    Increasing the complexity of Java so that language wonks will be able to write code more aesthetically pleasing to themselves (but less understandable for the people who might have to maintain their code) is a bad idea. No arrogant trash talk (“folks”) will change that.

    Where I work we are still using Java 1.4. Who *needs* generics? We’re much more interested in the various add-ons that give Java its power. If Hibernate, Spring, Lucene, JFreechart, etc. require 1.5, then we’ll move up, but not for new and unnecessary core language constructs.

  27. Augusto Says:

    Just because you are using 1.5 doesn’t mean you have to use generics. You can ignore the warnings.

    I take it that you rather not take advantage of fixed an improved features of a newer VM and new libraries that make sense (like 1.5 concurrency). Not all of us have the luxury to ignore improvements.

  28. Pinner Blinn Says:

    Augusto,
    To be clear, let me say that sticking with 1.4 for now is a business decision, and not a personal one. My company has invested a lot of QA on its applications, and our customers depend on our reliability. Sad to say, no version of Java is without bugs. I have had the experience of “upgrading” to a Java VM which completely killed my app (via a class cast exception deep within). More subtle problems are always a risk when deploying to a new VM.

  29. Masklinn Says:

    What about actionscript 3

    I’m not sure that’s a good example as AS3 is pretty much a breaking evolution, and a fairly complex one at that.
    I speak daily with flash users/coders, the ones who actually code love AS3 already and want to migrate everything to it, the others don’t want to learn how the new stuff works.

    For me, this is currently one of the big advantages of Java: the syntax is clear and almost everyone could read it.

    Do you have experience in any language beside Java? And by “any language” I don’t mean C or C++ of course.
    Because calling Java’s syntax “clear” and saying that “almost everyone could read it” is more than highly debatable. Almost anyone who knows java can read java, but that’s pretty much as far as you go.

  30. Howard Lovatt Says:

    Oops cock up with generics and HTML – 2nd try

    The C3S proposal for Java:

    http://www.artima.com/weblogs/viewpost.jsp?thread=182412

    Suggests:

    declare map = HashMap< String, String >.new(); // non final
    final map = HashMap< String, String >.new(); // final

    The above doesn’t break existing code and allows type inference for generics from arguments, e.g. assume that ArrayList had a vararg constructor.

    declare map = ArrayList.new( 1, 2, 3 ); // ArrayList< Integer >

    The comments about programming to an interface refer to the public signature of things mainly, not particularly to local variables. The advice to program to interfaces is a Java version of:

    Postel’s Prescription: “Be liberal in what you accept, and conservative
    in what you send”.

    Postel was talking about transmissions on the Internet, i.e. about public communication. In keeping with this public communications flavour; no changes are proposed to the declaration of method return and argument types (the accept and send parts of the quote).

  31. Jochen Bedersdorfer Says:

    Ravi, no-one says you MUST use an IDE.
    But for any kind of serious projects in any language, NOT using an IDE is a very, very bad idea.
    So your argument does not hold water.

    Also, the readability issue has not been refuted. If you have to read foreign code, seeing variable declarations is very helpful!

  32. Ravi Venkataraman Says:

    Jochem,

    Why doesn’t my argument hold water?

    Just because you use an IDE when developing with **Java** does not mean that other languages require an IDE. It is possible to develop large applications in some languages without using an IDE. In fact, it is easily possible to develop large applications in Java without using an IDE.

    Ask yourself if the complexity of your solution is a part of the problem domain, or is it caused by your solution itself. Most often, the complexity is caused by the solution and technology chosen.

    Java itself is verbose, which makes most people who use it to prefer some crutches (IDE) to help overcome the verbosity and lack of expressiveness inherent in the language itself.

  33. Masklinn Says:

    But for any kind of serious projects in any language, NOT using an IDE is a very, very bad idea.

    This is absolutely, completely and factually wrong.
    People have no problem developing complex Erlang applications (we’re talking telecom switches software, or avionics software, or airport tower control systems here) in Emacs or VI, people have no problem developing Haskell compilers in Haskell using the same kind of editors, people usually have no problem developing Python applications in pretty basic editors.
    IDEs are nice, but when you need to use an IDE, then your language has serious issues. IDEs are helpful tools, when they’re considered part of the core language then your language has a big problem, unless your language is Smalltalk and was built within and for an IDE coded in iself.

  34. Pure Danger Tech » Blog Archive » Java 7 Roundup (Apr 18th) Says:

    [...] also chimed in on whether type inference is a bad idea for Java. I originally thought that type inference would be pretty nice but my [...]

  35. Jochen Bedersdorfer Says:

    Masklinn, maybe we are speaking about different kinds of complexity.
    You are probably talking about difficult algorithms, maintained by one or two persons.
    I’m talking about HUGE enterprise applications with changing requirements, high-concurrency, complex user interfaces, > 100000 classes with at least 20 developers.

    Show me someone who, under this circumstances, for example, wants to refactor code without the help of an IDE?
    Also, getting around the code is probably about 10 times faster than without eclipse.
    Using “Open Type Hierarchy” and “Open Call Hierarchy” alone is a gift from heaven.

    You must be quite young to the business. I developed using emacs in several different languages (lisp, tcl/tk, prolog) and it is workable in small groups, no doubt about that.
    But as soon as you have to browse through huge class libraries, follow traces to find bugs, you must be absolutetly crazy to do it with emacs or any other simple text editor!

    My time is better spent with an IDE that saves me real time and I won’t even touch a new programming langauge, no matter how promising it looks like, without proper IDE support.

  36. Jochen Bedersdorfer Says:

    Raki,

    I don’t get this verbosity argument. It is rubbish.
    Java code is *simple* and that is a *good thing*. If your time is spent reading code you haven’t written or you have written but not touched in a while, code in static type languages is much, much easier to understand.
    You may call it verbosity or redundancy, I would call it self-documentation.

    As I mentioned above, it is possible to develop without an IDE, it is just a major bad idea.
    I know exactly how you feel, because I felt like this many years ago.
    It really depends on what you are doing!
    In my company, supervising the work of 5 developers I daily see the huge benefits of using an IDE.
    And no, I would personally force everyone to use an IDE even if we used Python or Ruby or whatever is hip right now.

    But, in retrospective of my earlier code, which was supervised by maybe one person and often written just by me, an IDE would still have saved me a dang lot of time. (if a good IDE would have been available at that time)
    Maybe you haven’t encountered the goodness of a great IDE yet.

  37. Masklinn Says:

    You are probably talking about difficult algorithms, maintained by one or two persons.

    I gave examples of what I’m talking about, hundreds of thousands of application locs by teams of more than half a dozen developers.

    I’m talking about HUGE enterprise applications with changing requirements, high-concurrency, complex user interfaces, > 100000 classes with at least 20 developers.

    Have you ever considered that the complexity could come from design decision and implementation language?

    Java code is *simple* and that is a *good thing*.

    I strongly disagree, Java code is anything but simple, Java code is both complex and extremely verbose. Java itself isn’t even simple, really, it’s just featureless. Erlang is simple, and Erlang code is simple. Java definitely isn’t.

    code in static type languages is much, much easier to understand

    How many times do we need to explain it before you guys understand that? Type inference is an exclusive ability of strongly, statically typed languages, dynamically and/or weakly typed languages can not have type inference.
    Type inference doesn’t make your code “less static”, if anything it makes the code more static and the type system stricter and more resilient.

    if a good IDE would have been available at that time

    If you pick the right languages, there have been (good) IDEs since the early 80s. Maybe you were just using the wrong language?

  38. Jochen Bedersdorfer Says:

    Masklinn, the examples you gave are from where exactly? Have you been involved in these projects? Are they current? (or from the 80s, where those things costed half a fortune)

    I strongly disagree, Java code is anything but simple, Java code is both complex and extremely verbose. Java itself isn’t even simple, really, it’s just featureless. Erlang is simple, and Erlang code is simple. Java definitely isn’t.

    Erlang is a function programming language, embedded in an interactive environment. Are we comparing apples and oranges again?
    Apart from that, where exactly is the Java language complex? I’m not talking about complex APIs or frameworks. That is probably what you are referring to.
    Java is a major simplification of C++ and everyone, but you, would agree that it is, indeed simple.
    Not as simple as Lisp, for example, but sufficiently so.

    Concerning featurelessness. What the heck are you talking about? Can you explain why Java is THE mainstream programming language nowadays? (and Erlang isn’t)

    Have you ever considered that the complexity could come from design decision and implementation language?

    That was especially funny. I sure did, dude. And before we chose Java as our main programming language, we carefully considered our options. Java is and will probably be for quite some time the most versatile, powerful and flexible platform for cross-platform development.

    How many times do we need to explain it before you guys understand that? Type inference is an exclusive ability of strongly, statically typed languages, dynamically and/or weakly typed languages can not have type inference.

    I have no idea what you are talking about here. I was referring to readability and understanding code by reading it. Having type information present is *helpful*. That was the only point to make.
    Having a more powerful type system is an entirely different discussion.

    If you pick the right languages, there have been (good) IDEs since the early 80s. Maybe you were just using the wrong language?

    Are you talking about 4GLs?
    Also, a nice major mode in emacs does not count as an IDE.
    Name me one IDE which supported code completion, quick fixes, refactoring, code measurement, building, packaging and delivering from the early 80s?

    Anything fruitful to add to the original discussion? Otherwise you should point me to a discussion forum, where we deal blows to each others pet language.

  39. George Says:

    Should have stopped bloating Java a long time ago. Well put Elliot.

  40. Zdeněk Machač Says:

    I agree that this type inference extension is bad. Example:

    final list = new LinkedList<String>();

    then compiler allow me write (and IDE completion help)

    list.listIterator();

    but changing declaration to

    final list = new ArrayList<String>();

    would not compile. It’s good practice to use interfaces and this is the best example. If I use

    final List<String> list = new LinkedList<String>();

    then newer can I write

    list.listIterator(); // compile error

    and must write

    list.iterator(); // ok

    and my code is ready to changing implementation. Type inference is against “Use interaface” pattern. When I want use features of LinkedList then is good to explicitly declare this is LinkedList.

  41. Ravi Venkataraman Says:

    Jochem,

    You said, “Name me one IDE which supported code completion, quick fixes, refactoring, code measurement, building, packaging and delivering from the early 80s?”

    OK. I’ll take the bait. Did not Smalltalk have all these in the early 80s? Not sure of the exact time, but I’ve heard that Smalltalk IDEs have had all these features for about two decades or more.

    As an aside, it is interesting that you think Java is a simple language even after working with LISP. Nobody claims that Java is more complex than C++ ( at least not until Java 1.4). Anyway, to say that a language is simpler than C++ doesn’t add any information about the language.

  42. Masklinn Says:

    Have you been involved in these projects? Are they current? (or from the 80s, where those things costed half a fortune)

    No and yes respectively (with “yes” being “second half of the 90s to today”)

    Erlang is a function programming language, embedded in an interactive environment.

    Erlang is definitely not “embedded in an interactive environment” (where the hell did you learn that?), Erlang applications are usually launched via a command-line tool that is used to interact with the environment indeed, but that’s completely different. The CLI is the interface to the Erlang runtime, not the runtime itself.

    Are we comparing apples and oranges again?

    We’re comparing two general-purpose programming languages, if that is comparing apple to oranges then any comparison of programming languages (including the comparison of C++ and Java) is “apple to oranges”.

    Apart from that, where exactly is the Java language complex? I’m not talking about complex APIs or frameworks. That is probably what you are referring to.

    Actually, I was referring to the syntax, the non-intuitiveness of the basic types (and the primitive vs object types dichotomy), the dichotomy between “base” types and user-defined types (operator overloading) and the original verbosity of the language.

    Java is a major simplification of C++

    Of course, I won’t disagree with that. Does that make it simple?

    everyone, but you, would agree that it is, indeed simple.

    Believe what you want, but i think you should start discussing with people who use languages other than Java and C++.

    Concerning featurelessness. What the heck are you talking about?

    I’m talking about advanced features such as first-class functions (and closures), actual (non type-erased) generics, metaprogramming constructs, a real, simple and workable support for concurrency (which admittedly very few languages have; Scala does though)

    Can you explain why Java is THE mainstream programming language nowadays?

    C-like syntax while being simple than C++, Sun’s and IBM’s marketting forces.

    Name me one IDE which supported code completion, quick fixes, refactoring, code measurement, building, packaging and delivering from the early 80s?

    Smalltalk’s environments.
    They didn’t have refactoring though, as the Smalltalk community created the notion of refactoring in the late early 90s (the first “official” paper on the subect I know of is William Opdyke’s Refactoring Object-Oriented frameworks published in 1993, the Refactoring Browser’s implementation started in ’94 and the base paper on the subject — A Refactoring Tool for Smalltalk was published in ’97)

    Nobody claims that Java is more complex than C++ ( at least not until Java 1.4)

    Even with Java 1.5 and 1.6, Java is still much simpler than C++ (the absence of C++ style templates alone is pretty much enough to ensure it)

  43. Mauricio Noda Says:

    Complains about too many changes in the Java language are becoming very common.
    “Java? Which version are you talking about?”

  44. Josh Allen Says:

    I’ve had a blast with Java over the years–I came aboard about the same time C++ collapsed under it’s own “evolution”.

    When I was younger I would have been all for new language features, but the more I’ve had to actually maintain code and worry about language problems besides how expressive and concise I can be, and have to agree 100%: create a new language that fixes the mistakes of the past, instead of retrofitting it where it doesn’t fit cleanly.

    By now Sun has provided enough tools for a very small group of people to make a new language: if you use the jvm you’ll have a huge libary and eco-system available.

  45. Bharath R Says:

    I’m glad you brought up the topic of the increasing “unteachability” of Java. Do the language a favor : next time, please laugh off (to put it lightly) anyone who tries to profess fancy versions of closures, a new property syntax or other such forms of geeky entertainment. The Java language is not some kind of a guinea pig on which you try out various experiments and, if they fail, throw it away and just pick up a new specimen. If they want to experiment with the language, ask them to use the kitchen sink . But please, let them not come up with complicated and absurd proposals just to kill time. What do they think they’re playing with?

  46. aehrenr Says:

    I have exactly the same opinion as the author.
    I feel more and more queasy with every feature proposal you can read on the web. It is like someone opened the Pandora’s box and now every possible personal pet feature is proposed to be included in Java with no end in sight. It is not that I think that many of the proposed features are good ideas, but its the sheer number of additions proposed to the language that will bring down Java. I am sure, eg. closures in other languages are useful, when the language is build around it. But a programming language should not be a bag of features but should have a clear design. And that is what is currently lost in Java! It does not make sense merely to throw all known features plus the feature of the season together and call that a programming language. After C++ was deformed, people take refuge in Java. Now Java is killed in the same way. I think the design of generics (and the auto-boxing thing) where already a disaster for the philosophy of java and now the rate of adding new features to the language should even accelerate? Next season we will have the same discussion of adding even more, lets say aspect oriented features, continuations or some other feature from a then hip scripting language.
    Sun should promote a new language that runs on the JVM like for example Scala, Groovy or something new, that is similar to Java (therefore easy to learn for Java developers) but with a consistent design.
    Keep also in mind: Java is not used merely by computer scientists but mostly by plain programmers or as a tool of people from other disciplines. Making it a wild assemblage of features and automatisms that no single person can remember (like C++) if the person doesn’t use the language exclusively and program the whole day, will destroy the Java phenomenon.
    So stop it and simply design new languages. I for instance like Groovy very much.

  47. Peter Parker Says:

    I can’t understand. For me, the compiler always will understand

    final map = new HashMap();

    as

    HashMap map = new HashMap();

    If you want Map or another interface, you must explicit it:

    Map map = new HashMap();

    Clear enough, ah?

  48. Masklinn Says:

    I can’t understand. For me, the compiler always will understand

    final map = new HashMap();

    as

    HashMap map = new HashMap();

    If you want Map or another interface, you must explicit it:

    Map map = new HashMap();

    As I mentioned, it has no reason whatsoever to work that way, using the context of this code (the way you’re using map) allows the compiler to infer the most possibly abstract types (in this case, there’s no reason why it couldn’t infer that map is of type Map). Moreover, since type inference requires an extremely extensive static type analysis (and the less formalized the type system, the more extensive the analysis requirements) the compiler would be able to warn you in case of inference to concrete datatypes (what ZdenÄ›k Machač gave an example of, in his own example it’s impossible for the compiler to infer to an ADTs because the code only works on a specific, concrete datatype).

  49. musaddi Says:

    public Map foo() {
    final map = new HashMap();

    return map;
    }

    this is understood by the compiler as HashMap. What’s the problem with that. Why do you want

    Map map = new HashMap();

    Probably you want to be able to change that to TreeMap later on.
    But you could do that, even with the above one. When you want it to be assigned to a Map reference you could always do that.For example you could return it as a Map.
    Want to change it to TreeMap? No problem change it. That’s ok. And if it is not compatible, compiler detects it.
    For eg.
    public Map foo() {
    final map = new TreeMap();

    return map;
    }

    Am I missing something?

  50. Robert Eccardt Says:

    In actual use, I don’t think it will matter much that the inferred type will be the exact type of what was assigned to it. It is not seen in the code and it can be used as if it were the interface type the programmer had in mind. When we say

    Map m = new HashMap();

    we know the underlying object in m is a HashMap anyway. By not making any kind of explicit type declaration at all for m, the best practice of always making the reference the least specific possible becomes moot.

    Even venerable old C++ is adding features, including type inference. In this article from over a year ago, Bjarne Stroustrup outlines the new features (they’ll use the keyword “auto” for type inference):

    http://www.artima.com/cppsource/cpp0x.html

    And this is Stroustrup’s proposal for lambda expressions and closures in C++:

    http://public.research.att.com/%7Ebs/N1968-lambda-expressions.pdf

  51. Augusto Says:

    Thanks for those links, had no ideas these features were being added to C++.

    It would be ironic if C++ gets closures while Java doesn’t …

  52. Ben Says:

    I really don’t like all the JCP proposals to add dynamic language features like type inference and closures by making the language more confusing and totally ignoring the core philosophies behind Java. This one, and all but CICE, make the language more complex and unreadable. If I wanted a language where everyone threw in every fad idea they could think of, I’d be writtting in C++.

    Personally, the feature I’d like to see added is Design-by-Contract similar to how Eiffel does it. I think it would be in line with the core principles of Java and greatly improve readability / robustness of code. Being able to define a contract in the interface and know that every implementor abides by it is simply strengthening current practices. And if it did cause enough of a performance problem (not likely, especially when RoR is the rage and is dog slow) it can be turned off for production but help detect errors early in QA cycles.

    All the features that Java-5 added I use every day, but I rarely find myself wanting any of the ones proposed for Java-7. When I read the blogs of those who propose the additions (like Gafter’s and Colebourne’s) its obvious they’re lost over-designing than dealing with real-world scenarios. I’d rather see Colebourne focus on cleaning up Joda Time for the JDK than screw around with another ugly closure implementation.

  53. emanuel Says:

    Interfaces like Map and List make sense as parameter types for public API method declarations, but not for local or private code/declarations. And also not for public API method return types.

    The statement that the local declaration List list = new ArrayList(); allows to use any kind of list is wrong:

    you have to change the code exactly there where it is used:List list = new LinkedList();
    just look into the JDK collection API documentation how often Sun changes the semantic of overwritten methods. Example: Collection.add(Object) adds element anywhere while List.add(Object) specifies it to append the element. Not to mention that in both cases add(Object) is an optional method, which your code then should not use if it should be able to deal with any List implementation.
    even if the semantic remains the same when switching to a java.util.LinkedList, you will not want to write e.g. for( int i = 0; i but use an iterator instead, because indexing in linked lists is horrible slow.

    Again: using interfaces instead of real classes makes sense for public API but not for local or private code.

    And as shown in the above list in most cases it is even important to know whether some code is dealing with an ArrayList or with a LinkedList. And not only at the location where the variable was initialized.

  54. Michael Nischt Says:

    In principle I like that everything is final by default or the nicer syntax with the special operator ‘:=’. However, I agree it would mess up Java’s style.
    Further, nobody will argue against that:
    final Map<String, Integer> map = new HashMap<String, Integer>();
    is a better coding style than:
    final HashMap<String, Integer> map = new HashMap<String, Integer>();
    Which why I’m also against:
    final map = new HashMap<String, Integer>();
    IMHO, specifying types is not the problem, but double writing for type-paramters sucks. This is why I’d like to see an automatic generation of an overloaded new-method for each constructor:
    final Map<String, Integer> map = HashMap.new();

    Besides, that ‘new’ is a reserved keyword, one could also do that by hand and the type-paramters would be inferred whenever possible. Luckily this makes ‘new’ an ideal candidate for a language addition :-)

  55. emanuel Says:

    Further, nobody will argue against that:
    final Map map = new HashMap();
    is a better coding style than:
    final HashMap map = new HashMap();

    Well, I just did argue against it. See entry just above yours.
    Here some more reasons: you also don’t write:

    Number n1 = 3;
    Number n2 = 3.7;
    CharSequence s = “hi”;

    If you don’t care about the precise type then use a scripting language, but not Java.

  56. Rob Griffin Says:

    but double writing for type-paramters sucks

    If you use Eclipse then you never need to type the type-parameters more than once; Eclipse’s code completion fills them in for you. I would image (or hope) that other IDEs can do the same.

    At the moment I’m doing a bit of C# which supports duck typing using the var keyword. I don’t like it much because if the variable is being returned by a method you can’t readily see the type.

    E.g.
    var x = getClients();

    What type is x? Also the IDE can no longer go to the definition of the type because var is a keyword.

    In Java I use Eclipse to do the work for me; quick fix can create a variable to hold the return value of a method and guess a name based on the method name e.g. the quick fix ‘Assign statement to new local variable’ on getClients() will result in a variable called clients of the type returned by the method.

    So I think the answer is to use the right tools. No language changes are required .

  57. bohan Says:

    i cannot disagree more with the authors’ resistant point of view. Type inference becomes a necessity to be able to write readable code when parametrized types are used a lot, because type names can become very long and tedious to read. Ever wrote loops that iterate over parametrized containers in C++? I wish C++ would introduce type inference in standard too (it has typedef, which can reduce type name bloat, but it’s not as nice as inference, and typeof is not standard and not as nice either)

  58. Carlos Says:

    > Type inference actually makes some sense in languages like JavaScript and PHP that are built around this, and had this feature from day 1

    Oh, my friend! you have no idea what type inference is for an statically typed language…

    http://en.wikipedia.org/wiki/Type_inference

    However, java is not 100% statically typed – presents itself like that, but it isn’t – and in this sense similar to PHP.

    I recomend for anyone reading this to look for Haskell or Concurrent Clean to see what type inference mean (or Scala, which already has it and runs on the JVM)

  59. Barney Says:

    Isn’t everyone missing the point? If we want to reduce clutter and keystrokes, It is the RHS which should be inferred, not the LHS! Never understood why Java didn’t support C++ style instantiation from day 1 – the new operator is completely unnecessary in Java.

    /* StringBuilder builder=new StringBuilder(64); */

    StringBuilder builder(64);

    /* LinkedHashMap<String, ArrayList> map=new LinkedHashMap<String, ArrayList>(); */

    LinkedHashMap<String, ArrayList> map();

    Seldom is there any benefit in declaring a variable as the interface rather than the concrete type we know we will instantiate it to, and in these rare cases the existing syntax will do fine.

  60. tiny tim Says:

    Hogwash… Who is forcing you to use language features you don’t want to?

    Quite a number of strongly typed languages support type inferencing, join the rest of us in 2010 when you catch the clue train!

    That said… I don’t see why we need this: x := “duh” , business, x = “duh” should be sufficient.

    Explicitly asking for type inferencing is the sort of goofy crap that led to the orginal bloat this sort of feature was meant to combat in the first place!

    Type inferencing should be done at compile time (hello javac, g++ calling) not at runtime.

  61. Anonymous Says:

    1. Misunderstand proposed language feature.
    2. Get angry about how you don’t like it.
    3. Complain that Java already has too much different syntax anyway.
    4. End in praise of C#, which is suffering from a much more severe case of syntax cruft.
    5. ???
    6. Profit

Leave a Reply