Forget the shackles of backwards-compatibility. If you could make changes to Java to make it a better language, what would you do? I don’t mean drastic surgery so that you end up with Lisp on the JVM, but what could be done to make Java a better platform-independent, object-oriented language?
Bruce Eckel has some interesting thoughts about the evolution of Java and Sun’s commitment to backwards-compatibility. I have to agree that backwards compatibility will eventually kill Java if new features are continuously compromised by nasty hacks (e.g. erasure) to avoid breaking legacy code. At some point, the guardians of Java must choose new features or backwards-compatibility. To continue to demand both is not sustainable.
With this in mind, I’ve made a list of things that I personally would like to improve in Java, assuming that backwards-compatibility is not a primary concern. I’m interested to hear others’ suggestions, so leave a comment at the end if you have better ideas.
If it weren’t for Sun’s marketing department, we could have called it Java 2. Java++ is just wrong, so I’ll follow Cedric’s naming scheme and call it JavaNG – the next generation OO language for the JVM.
Maybe it’s just me, but this really bugs me…
Firstly, and it may seem trivial to most, but I would scratch an itch that has been bothering me for over a decade. The
Cloneable interface does not define the
clone() method. An object must define a public clone method in order to be cloneable, but the
Cloneable interface does not require this. Therefore it is perfectly legal to implement
Cloneable yet not be cloneable. Of course, any class that does this is obviously broken, yet the
Cloneable interface apparently cannot be changed since such a class would no longer compile. In my opinion, Sun would be doing developers a favour by making the compiler complain about this. FFS Sun, you broke everybody’s code by adding the
assert keyword in 1.4, why would fixing
Cloneable be such a big deal?
Is this an object-oriented language or not?
Right, now on to more substantial concerns. Primitives have to go. Everything should be an object. It would simplify learning the language and primitives don’t mix with generics without auto-boxing (and auto-boxing is horrific). No primitives – no auto-boxing – no problem.
I believe that primitives were originally included in the language because of performance concerns about doing everything with objects. Well virtual machines and hardware have both moved on significantly since the mid-90s. And if Ruby seriously is the main competition, then performance clearly doesn’t matter anyway.
BigDecimal.ONE.add(BigDecimal.ONE).compareTo(new BigDecimal("2")) == 0
Obviously if there are no primitives to unbox to, then the arithmetic operators have to be defined to work on the appropriate object types (
java.lang.Double, etc.). But why stop there? Arithmetic operators for BigInteger and BigDecimal are long overdue. Without first-class support for arbitrary-precision arithmetic, Java is not a sensible choice for many types of application. I mean, how hard should it be to assert that 1 + 1 = 2?
Types are for life, not just for compilation
I want generics without erasure. Since I can accept breaking backwards compatibility where necessary, I don’t have to accept a weaselly implementation compromise and the resulting frustrations of not being able to inspect type information at runtime.
Just say no to null
For a language that supposedly doesn’t have pointers, there are an awful lot of
NullPointerExceptions in Java programs. The simple truth is that developers have proven to be incapable of keeping track of which references are allowed to be null. I want the language to do this for me. More specifically, I want the type system to do this for me. The Nice programming language has the concept of option types. I want one of those. If my method declares that its parameter cannot be null, then any attempt to pass it null (or even to pass it a value of a nullable type) should result in a compiler error. Non-nullable types will become the new ‘final fields’. They’ll be used everywhere unless there is a good reason not to.
Java’s verbose they say. Well Java will always look a bit wordy when compared to Python with its sleek dictionary syntax. But we could have that too. Literals for maps and lists would help to make code more concise and more readable.
According to Gilad Bracha, Java was supposed to have had tuples from the start, they just never made it into the language. It’s time to rectify that. No more writing several trivial little classes (or generic Pair and Triple classes) just to wrap together multiple return values.
The stuff that didn’t make it…
I think that list is long enough for now (though I’m sure I’ll think of more later). You’ll notice that I haven’t taken a position on closures. I’m unconvinced and undecided. I need to read the proposals properly. In the past I’ve advocated first-class functions for Java, but for now I’m deferring on that too, at least until I’ve picked a side in the closures debate. I also think that the original Java designers got it right when they left multiple inheritance and operator-overloading in C++ land.
If you think you have a better plan for JavaNG, please add a comment. I’ll post a follow-up in a few days summarising the suggestions.