loading...

Java 15 in 2020: Reasons to *not* use Java?

brunoborges profile image Bruno Borges ・1 min read

In 2020, Java 15 will be released with major features (some coming out of preview mode), both at language, API, and runtime levels.

https://openjdk.java.net/projects/jdk/15/

Considering the changes that have already made through since Java 8 and the upcoming changes in Java 15, what are in your opinion the use cases that no longer make sense to use Java, and why?

Discussion

pic
Editor guide
 

[Disclosure: I haven't used Java professionally for a year but I had worked with it continuously for the 20 years before.]

This is going to appear like a collection of random thoughts, but please bear with me.

Let's start with the easy stuff, client-side Java.: just no. It's always been clunky but had the advantage of a relative ease of multi-platform distribution. Note that this was an amazing feature nothing else would match at the time. However it was also hideously insecure and instead of fixing it, they nuked it. And without that, only the clunk remains.

Verbosity is an issue but not as big as it's made out to be, at least in the long run: while it steepens the initial phase of the learning curve, once you're up and running and use a modern IDE, it makes little difference.

A thing often overlooked is the Java Language Specification. It's a tremendous asset. There is great value in being able to reach back to a formal definition of every language structure that is only appreciated when you start working in a language without one. However, if you know the JLS inside out, you will also be aware of where holes had to be cut out to accommodate new features. And the number of these holes is growing.

The fact you can take a piece of code written and compiled 10 years ago and run it now is a double-edged sword. Compared to the here-today-gone-tomorrow nature of JS libraries, it definitely feels nice to have some kind of longevity (especially in a corporate environment), but it comes with a price that gets heftier with time (see also: holes in JLS).

Another thing worth mentioning is that the Java language and the Java VM are two increasingly separate entities and as far as I'm concerned, the VM should be made the flagship product (if it hasn't been already).

So why else would you not choose Java? Well, Oracle. And not just Oracle in general.

The "new" release cadence seems to have created a "worst of two worlds" chimera: features aren't getting implemented much faster than before but licensing and support have become much more complicated and seemingly designed to discourage people from wanting to work with Java. I haven't got anything more to say on this other than if you do use Java, try to pretend non-LTS releases are simply overnight builds: fun to play with but shouldn't be anywhere near production.

So to sum it up: is Java still worth trying? Yes, I would say it is, if only in the same way Latin is still worth learning. Java still features important concepts and ideas that are worth knowing even if eventually you choose to go with another language.

 

Thanks for sharing these thoughts.

I do have a few comments/questions to add and perhaps clarify.

First, I'd like to understand better your comment on client-side Java and security issues. Are you referring to the Java Plug-in for web browsers, or are you referring to Swing and JavaFX?

On verbosity, I can't stop to think whether this comment is "by looking back", or "by looking at Java as of today". In other words, haven't the latest language features (up to Java 15) helped at all reduce the verbosity while keeping readability?

What holes have been added to the Java Language Specification in your opinion? What is missing? And how backward compatibility, maturity and stability can be a good and a bad thing at the same time?

In your opinion, how licensing and support have impacted users, considering that Java continues to be free, and with multiple choices of companies to choose commercial support from. If anything, what Oracle did was to start charging for production use of their commercial binary of Java, while still offering GPL2 binaries too, and with other companies in the market that have been doing that for years.

 

Good questions.

  1. I was referring to applets, WebStart and the browser plugin: the methods of distribution of client-side code. These were inherently insecure and while they could've probably been replaced, they weren't. As for Swing and JavaFX, they're the clunky part of client-side Java. They certainly do the job but...

  2. They absolutely have helped massively. But there is a reason Project Lombok still exists, there's still a lot of what many would consider clutter in vanilla Java. (Then again, the fact that something like Project Lombok CAN exist shows the power of the platform and the tooling.)

  3. "Holes" was probably a bad word, as we're not talking about undefined behaviour but about things that used to be simple, and then had a really complicated thing bolted on top of it. Take a look at type inference for example: docs.oracle.com/javase/specs/jls/s...

  4. That is true but what I saw in practice is that it just confused everyone, both end users and companies. Now this might have cleared up over the time I spent away from Java, but back then I did have a nagging feeling that it's almost like they were trying to make this as difficult as they can. I could of course be completely wrong but I can't really explain it any better.

On the client-side, it is worth to anyone (Java developer or not) to revisit JavaFX. At the bottom of the OpenJFX website, there is a set of use cases. There's also this amazing tool to demonstrate the power of the platform these days: Binjr.

On the JLS point, I think it is well defined. Yes it is long, because it covers all aspects of where type inference may occur, and how. One doesn't have to learn Java by reading the specification though. Many great authors have been able to translate the technical specification into more easily consumable books. Again, touches the ecosystem vibe. A good thing IMO.

In many cases, especially on Linux, one simply does apt install openjdk and boom, they get a binary of OpenJDK. On Mac and Windows, from a developer perspective, it is indeed a bit more confusing given that there is no longer "go here and get Java". But there is progress in this area with packages now available over Homebrew, and JDK managers like SDKMAN.

Thank you, it's good to here that things are improving on the packaging front.

With JavaFX, while I really liked working with it, its weird half-in, half-out status it had for a long time was a big mistake in my opinion, and put many developers off. It still felt a bit clunky at times (could be that I wanted to do clunky things though), then again, if I had to write a thick desktop client now, it'd probably be my first port of call.

The JLS is of course well defined, the problem is that its complexity explodes with each new major feature bolted on. Now, I used to dig into the JVM on a fairly low level, so maybe this affected me more than most, but it was hard not to notice how the number of compiler bugs went up, signalling that leap in complexity.

The problem of course arises not from the new features, which are all fine, but from the need to maintain backward compatibility, so historic compromises (like the covariance of arrays) have to be tiptoed around. As I said, it's a double-edged sword.

 

The reason to be using Java in 2020 is because you are already using Java.

Now, unlike some others here I don't hate Java - having developed on it for over a decade plus having it be the core of my university experience I recognize the benefits it offers. The problem is that it has downsides, mostly from 90's legacy architecture, that its alternative don't have. Pretty much all of the cool features from Java 9+ are new features...to Java. Take Jigsaw for example - creating a dynamically sized runtime that has just the features you need, nothing more. It was exciting when it finally came out (the fact that it took so long also comes from Java's legacy architecture) because it as a problem that Java had for along time. Some of the alternatives either never had that problem in the first place (NodeJS) or had the problem but fixed it a lot sooner (.NET Core). With the exception of Fibers, there's nothing in the JEP pipeline that I've seen that isn't either already available or will be made available sooner on one or more of Java's alternatives.

 

What are in your opinion the reasons to not start using Java today, considering the latest features in the language, APIs, and runtime, since Java 8?

 

Good question!

Fundamentally it's about longevity. Sure, you could start with Java today and it would probably satisfy your needs. But what about a year from now? Two? Five? By those points there will be new capabilities you might want that Java probably doesn't have and it's alternatives will. If you are already on a leaking ship you are going to try to keep it afloat, at least until you reach your destination. But if you are standing on the docks why would you choose to get in the boat that's already leaking?

And what makes you believe that the Java boat is leaking?

Because the trajectory of Java is downward when compared to the alternatives because it is getting new features slower.

Lets say I create the same app twice, one using Java and the other using .NET. In 5 years time I believe the best thing you could say is that the Java one is no worse off because the new stuff that .NET has that Java doesn't have doesn't apply to the app. And I'm struggling to come up with a scenario where the Java one would be better off.

The risk that your choice might not be good enough for the long run? That's getting into a leaky boat.

 

First, some context on my reply:

I began my career writing Java and PHP a long time ago. Now, I mostly write Go. I am a devops engineer by day and I also write tools for tabletop role-playing games.

Now, to my reply.

Java's verbosity is its fatal flaw for me. I can write a command line program in Go that is 10% of the size of the same program in Java with a smaller memory footprint and a faster runtime.

This is not to say that Java is always the wrong choice. If a business is already using Java, then it makes sense to continue to use Java. But I will never recommend it for a new project.

 

This is what always gets me too, and is why I have always avoided Java. It still takes much longer than it should to read Java code because simple things require so much code. Even C#, which was originally based on Java, manages to be a lot more concise.

I’m glad to hear you say Go doesn’t have this problem. I’ve looked at Go briefly, several years ago, but haven’t spent a lot of time with it. I got the impression the error-handling in Go makes it really verbose. But I heard that’s supposed to get better in Go 2.

 

Hasn't features like Type-Inference (var), lambdas, new APIs in the Collections Framework, and recently Records and pattern matching helped in any form to reduce the verbosity?

I mean, this is a possibility with Java 15:


public record Person(String name, int age) {}

public class Process {

  public void process() {
    var p0 = new Person("a", 18);
    var p1 = ...;

    var list = List.of(p0, p1);

    // sum all ages
     list.stream().mapToInt(Person::age).sum();
  }
}

Yup, glad to see those advances. It’s taken much, much too long IMO for the language to catch up and introduce things like that. I gave up on it before those were part of the language, and that was after 15 years of waiting.

 

Error handling in Go is verbose. That's true. However, the verbosity of error handling in Go is a little different, in that it forces you to acknowledge potential fail states in your code. Also, if you really want to, you can completely ignore error handling entirely in favor of concise code. That makes me twitch, but it's possible.

To be clear, I wasn’t implying I like to ignore error handling. Just that I like it to be concise.

Aren't checked exceptions in the same area as "forcing developer to acknowledge potential fail states", while allowing developers to ignore them if they want to, and also allowing developers to purposely going with unchecked exceptions if they prefer?

 

This is an interesting article showing how a company chose to go with Java instead of C, C++ or even Rust to orchestrate an automated robot swarm for supply chain.

I wonder what other developers with experience in this space think of using Java to control robots.

Ocado Technology on why it uses Java to control its robotic swarms

 

Because it is intimately associated with Oracle and they're a terrible company? .. I have personal experience with this (astounding) terribleness but will not share anything concerning it (in print) because they seem to have A LOT of semantical sentence parsing lawyers itching for someone to drag into a deposition. Seriously, I don't care if it's the greatest thing since sliced bread, you should always avoid Java - otherwise you'll be dealing with (what I consider) a law firm masquerading as a tech company.

 

One doesn't have to rely on Oracle at all to use Java today, given the source code is GPL2 and there are many other companies shipping their own distributions of Java: Azul Systems, Red Hat, SAP, IBM, BellSoft, AdoptOpenJDK, and couple others.

It intrigues me how an open source language and runtime, because it is stewarded by Oracle, but with contributions from many other companies and individuals, would still scare people away.

Mind to share more insights about your perspective?

 

I know about OpenJDK and whatever but, like I said, have personal experiences with them as a corporate entity. Do you really understand how that licensing works (and are you SURE?) I'm POSITIVE I understand how their "professional services" operate and I'm also aware they're suing Google over a clean-room clone of a freakin API (and I assume they bought Sun for this exact reason). I will not go into details here (but over a drink, sure!) but for me it boils down to thing "Do I trust them" and the answer to that questions is an unequivocal NO

Fair enough! :-)

 

The lack of immutability as first class citizen! It introduces so much guard code. You. an never trist anything.

 

Well, immutability is just a final away. Maybe you meant "lack of immutability as default"?
What do you mean as "first class citizen"?

 

Even with final, a List is still mutable. I like the idea to explicitly make things mutable and have immutable types per default. Just the noise of the verbosity code.
I normally end up having a large code base in a class, to prevent the class from being abused. So the next developer needs to read all the code again, ...

There are ways to cope with that. But if you are really hurt by the verbosity yes, you can only get that short in Java. There are alternatives, even on the JVM.

On the JVM I like atm Kotlin the most. I have worked with C# and F# and now the company uses Java. But for me on the long run, I will try to focus on Kotlin.

But isn't this code clear, non-verbose and with an immutable list?

import java.util.*;
import static java.lang.System.out;

public class Hello {
  public static void main(String... args) {
    var a = "a";
    var b = "b";
    var c = "c";

    // immutable list
    var immutList = List.of(a, b, c);

    // create a mutable list of the strings above
    var l1 = new ArrayList<>(immutList);
    l1.add("d");

    // turn list back to immutable
    var immutList2 = Collections.unmodifiableList(l1);
    immutList2.forEach(out::println);
    immutList2.add("e"); // runtime exception
  }
}

From my point of view I mostly use the of() functions to create a data structure. But while the list itself is immutable the elements are still mutable.

public class Main {

    public static void main(String[] args) {
        var a = "a";
        var b = "b";
        var c = "c";

        List.of(a, b, c)
                .forEach(it -> it = null); // mutate the data
    }
}

And I think here is the think that often ends in the NPE hell. Some people write very protective code, where everything that could be null, is checked for null. There is no concept like val from the Kotlin world.
So from what I saw in the code bases I worked with is, that some people are using something like this:


void doSomething(List<Item> items, Data someDate) {
  ...
}

When I go through those methods, they mutate some items or all of the list. Now here you need to be aware, that the list is passed by ref. So testing and complexity of the code is not super trivial anymore. So what I meant with first class citizen is the idea, that from my point of view it should be easy to not mutate a state and write pure functions and mutating the state should need much more verbosity code. But that is what I think.

List.of(a, b, c)
       .forEach(it -> it = null); // mutate the data

This code doesn't change the data at all. The list continues to be the same after the forEach. This code above is the same as this:

        var a = "a";
        var b = "b";
        var c = "c";

        var list = List.of(a, b, c);
        list.forEach(it -> it = null); // mutate the data
        System.out.println(list);  // prints [a, b, c]

        for(var x : list) {
          x = null;
        }
        System.out.println(list); // prints [a, b, c]

The data continues to be immutable.

If you need val immutability, Scala is just a few jars away, And VSCode support with Metals is getting really good.

 

Fun fact: final classes with only final fields are NOT entirely immutable.

 

2020?, it comes with viruses :)

 

Everything does, except beer. :-)

 

Unless it's called Corona... =P

 

Not sure I quite understand the question - why would the addition of features to Java (which I assume are an improvement to the language) suddenly cause Java not to make sense anymore for certain use cases?

I'd rather turn the question around - for which use cases might Java become more attractive because of the addition of these new language features?

 

Since the JVM support split, it is much harder to sell a simple coherent message to non-technical people. I think this is a big reason it is hard to get off Java 8. With Go you can point at the website and say look, it's all here and Google made it. If your employer could wrapper Azul Zulu and put a logo of a company that people had heard of it would be easier.

 

I get your perspective, but aren't open source projects with multiple implementors and sponsors better than monopolized open source projects?

One of the beauties of the Java platform is having a true single source code, GPL2 licensed, and having multiple companies one can choose commercial support from. Plus, a variety of languages beyond the Java language itself (Scala, Kotlin, Ruby, Clojure, to name a few).

When someone "apt install python" on their Linux server, they are getting a binary of Python compiled by that Linux distribution team (e.g. Canonical, Debian, CentOS, etc). Same thing happens when someone "apt install openjdk". And on top of that, one can download binaries of OpenJDK from different specialized vendors who build Java from the source and provide commercial support (Red Hat, IBM, SAP, Oracle, Azul Systems, BellSoft, to name a few).

Isn't this an advantage?

 

I think it's nuanced.

Of course having competing products results in better performance and better price and that's an advantage...

But it also results in more choice, and that is both an advantage and a disadvantage. I don't think I care about my hair - but when I have to buy shampoo in a foreign supermarket, it is an arduous choice.

Think about all the terrible software decisions based on default choices and laziness. All of the banking enterprises that have been run on Excel spreadsheets that get backed up when someone remembers.

Java was always meant to be the language that wouldn't get you sacked, it was an easy default choice - and I think it has lost some of that power.

One of the major values of open source is being able to choose who you want to sign a support contract with. An open source project that has a single company providing commercial support and stewarding the project seems like a weak open source project to me.

While I see that it can complicate things, it can also really make it easy. As someone pointed out here before, they don't like Oracle. Fair enough, just go choose someone else. Now imagine not picking on a technology despite all of its benefits just because you don't like the only company maintaining it. Java is different with this regards. It has multiple companies maintaining it and one can get commercial support from someone else with ease. I can't really see how this is a disadvantage.

 

For production development, I'm sticking with the long-term support releases, so java 11 for me until version 17 in Sep 2021. Should be lots of nice new stuff for me by then!

 

I think in most places that's the case. I do fear loom might not be part of it yet. Which means another three years, and if that's the case it has a big disadvantage compared to other languages. It nice they want to keep being backwards compatible, but it's making any fundamental changes really hard.

 

As someone who started out as a Java Developer and considers himself a polyglot developer now, I would still use Java for the following

  • Web apps server-side
  • Microservices where memory/overall footprint is not a priority
  • On any given day over Scala/Clojure for applicable use cases :P

Where I would not use Java is

  • Client-side desktop, I know JavaFX is better now but still, there are many other better cross-platform alternatives like Electron etc IMO
  • Client-side web: no way
  • CLI tools, again I know you can do it but I cannot justify it when NodeJS, Go, and even Rust is a much better option for that
  • Web assembly
  • Mobile (not counting Kotlin for Android)
 

I'd love to answer you question, but in order to write a Java comment I need to first create a AbstractJavaCommentFactory, then a AbstractJavaComment, then an JavaCommentFactoryImpl and finally a JavaCommentImpl, and I usually forget what i was going to say by the time I get that far... :-)

 

Sorry, but I don't think it is a good question. The "use cases" you mention are not a strong enough concept to provoke a development manager to propose a costly learning or hiring endeavor for his team to his patrons in a time of worldwide recession, while Java is still such a big player in the tech market. They done it with Java so far, they will continue doing it with Java for as long as it remains cost effective.

There are contenders for sure, but as a language and API, Java is sound, powerful, and is VERY active.

It's just NOT the way management decides.

 

I hate the records with .name() and .method() instead of getName getMethod... this breaks all libraries even JSTL :(

 

There's discussion on the mailing lists to let the bean inspection APIs return proper BeanInfo instances for records, too. I.e. .name() would still constitute a "name" property with a ready method of name(). That should make existing libraries work with records OOTB.

 

That will be GREAT if it happens, because to patch ALL libraries is a disaster especially with the Java EE to Jakarta EE and JSTL impl or JSF being part of the web container in some cases.. it becomes a huge mess.

I still like get more btw... it's better to be consistent even not great, then inconsistent.

 

I wrote an article on github on modern Java: intuition-dev.github.io/SNX/#/README