Java 7 Project Coin – Why Were Null-Safe Operators Rejected?

api-designjava

One of the proposed features for Java 7's "Project Coin" was the "Elvis operator". A report of a 2009 JavaOne presentation on Project Coin described it as such:

One of the "small features" covered in this presentation is the so-called "Elvis operator," a more concise version of the ternary operator. I find myself missing some of the features of Groovy when using traditional Java and this would be one operator that I could use in both languages if it was added. The "Elvis" operator is handy for specifying a default value that can be used when the evaluated expression is null. Like Groovy's safe navigation operator, it is a concise way to specify how to avoid unnecessary nulls. I have blogged previously about how I like to avoid the NullPointerException.

While other aspects of Project Coin were ultimately implemented, this one was not. Why was the Elvis Operator ultimately rejected, despite being presented at JavaOne as a likely candidate for inclusion?

To be clear, I'm specifically asking about this operator and the reason it was rejected as part of Java 7's "Project Coin", given that it was seriously considered then. I suspect that there are mailing lists or such where the reasons for rejecting it were discussed, but I couldn't find anything. If there is more general information about why it is not included in any version of Java, that is acceptable but not preferred.

Best Answer

Naturally, the best person to ask this question is someone on the JCP Executive Committee, not us. However, that won't prevent me from engaging in some idle speculation.

The answer to every "why wasn't this feature implemented" question is always because the benefits did not exceed the costs.

Eric Lippert (former member of the C# team) says that, in order for a product to have a feature, that feature must be:

  • thought of in the first place
  • desired
  • designed
  • specified
  • implemented
  • tested
  • documented
  • shipped to customers

In other words, there must be many important things that must happen before any new programming language feature can be realized. The costs are larger than you think they are.

On the C# team, every new feature request starts out with a score of minus 100. Then the team evaluates the benefits and the costs, adding points for the benefits, and subtracting points for the costs. If the score doesn't go above zero, the proposed feature is summarily discarded. In other words, the new feature must provide a compelling benefit.

But the Elvis Operator made it into C#. So why didn't it make it into Java?

Despite their apparent similarities, Java and C# have significantly different language philosophies. This is evidenced by the fact that Java enterprise programs tend to be large, structural collections of architecture. Brevity and language expressiveness are sacrificed on the altar of ceremony and ease of coding. Well-known software architectural patterns that everyone on the development team can recognize are preferred over language conveniences.

Consider this Reddit exchange:

The Elvis operator has been proposed for every version of Java since 7, and has been rejected every time. Different languages fall on different points along the spectrum from "pure" to "pragmatic", and languages implementing the Elvis operator do tend to be further toward the pragmatic end of the spectrum than Java.

If you have a team of 15+ year Java pros writing a highly-distributed, highly-concurrent backend processing system of some sort, then you probably want a great degree of architectural rigor.

However, if you have a junior to mid-level team, half of whom migrated from Visual Basic, and you have them writing an ASP.NET web app that mostly just does CRUD operations... then it might be overkill to design a bunch of AbstractFactoryFactory classes to abstract away the fact that you have no control over which columns are nullable in the shitty legacy database that you must use.

These profound differences in language philosophy extend not only to the way the languages are used, but to the way the language design process itself is undertaken. C# is a benevolent dictator language. To get a new feature into C#, you only really have to convince one person: Anders Hejlsberg.

Java takes a more conservative approach. To get a new feature into Java, it must get consensus from a consortium of large vendors such as Oracle, IBM, HP, Fujitsu & Red Hat. Obviously, that process is going to be slower and present a higher bar for new language features.

The question "why wasn't x feature implemented..." always implicitly includes the words, "...if it's obviously such a good idea?" As I have adequately demonstrated here, the choice is never that simple.