Java is dead. Leave the sinking ship, Kotlin, go, whatever it is, learn another language!
Is that really true?
History
Let's look at the history first. I've been doing Java development since about 2005, starting with embedded devices programmed in J2ME. Java SE (or J2SE) was already at version 1.5 but in J2ME, the language was compatible with Java 1.3 and only a subset of the JDK was supported. E.g., it didn't even had any Map implementations.
At the time of writing, Java 13 has already been released and it's been a hell of a journey. Since Java 1.3 over the past 17 years we've had features like those being added:
Java Version | Selected Features |
---|---|
1.4 | Regular Expressions, Non-blocking I/O |
5.0 | Generics, Annotations |
6 | JAX-WS, JWM + Compiler extensions |
7 | Dynamic languages support |
8 | Lambdas, streams, optionals |
9 | Module system, JShell |
10 | var keyword, Graal |
11 | Running Java files like scripts |
12 | Switch expressions |
13 | Text blocks, Class data sharing |
NIO is still the base of non-blocking and reactive web frameworks. Without annotations, aspect-oriented programming that e.g. the Spring framework leverages would have not been possible. Extensions of the compiler made Lombok possible. Lambdas, streams and optionals moved Java closer to a functional programming style (although it's still not a functional language) and allowed to reduce the amount of boilerplate. Switch expressions are a little step on the road to pattern matching (see section below). And dynamic language support made it possible or at least easier to bring dynamically typed languages like Ruby and Python to the JVM.
Sources: - https://howtodoinjava.com/java-version-wise-features-history/ - https://en.wikipedia.org/wiki/Java_version_history
Java = JVM + Language
When we talk about "Java", we should actually talk about the Java Virtual Machine (JVM) and the Java language.
When you run a Java application, the Java source code (*.java
) first has to be compiled to Java byte code (*.class
) which is the same on all platforms, hence the slogan "Write once, run everywhere". The byte code is optimized to be interpreted and run fast instead of directly interpreting the Java source code as it is done with JavaScript e.g.
The JVM itself is a platform specific implementation (e.g. Linux, Windows, Mac) of a Java runtime. It basically takes the previously generated byte code and runs it on the target environment. In the early versions of Java, the byte code has been interpreted which was relatively slow. From Java 1.3 on, the HotSpot VM which is a Just-In-Time (JIT) compiler has become default. It identifies high-frequently run code (i.e. the "hot spot" within the code) and compiles the byte code to native machine code which is much faster.
Since then, a lot of smart people at Sun / Oracle have improved the the JVM to be extremely fast. And by "extremely fast" I mean comparable or even faster than an equivalent C++ implementation because the JIT can generate more optimized machine code based on the known CPU and knowledge about the actual code and data flow at runtime.
Don't Follow the Hype
That is the reason why the JVM ecosystem is flourishing, setting the stage for a whole set of new language that compile to Java byte code:
- Groovy
- Clojure
- Jython
- Scala
- Kotlin
There is a long and growing list of others.
Recently, I found this in my twitter timeline:
This looks amazing right? First, let's have a look at what it is. It's the percentage of questions asked about that language that month. So, Kotlin is a relatively new and also popular language, no doubt about it. So, naturally, a lot of people are asking questions.
But wait... one language is missing! What about Java?
So, Java has still about 10 times as much questions as Kotlin which has passed Scala. What about popularity?
Source: https://www.tiobe.com/tiobe-index/
So Java is still #1 (I know, TIOBE results are debatable). Let's see where Kotlin and Scala are... Rank 30 and 35, respectively.
Ok, what about job opportunities? As a Java programmer, you don't have to search very long to find a decently paid job offer in the industry.
https://hackr.io/blog/best-programming-languages-to-learn-2019-jobs-future
So don't get me wrong: I love new languages, especially when they bring new concepts that expand your horizon a bit and push other languages to adapt faster. Go and learn them!
A few years ago, Scala has been hyped a lot. People were saying that it is going to replace Java. Although Scala has some very appealing features, eventually it didn't.
Currently, Kotlin is hyped a lot as well. It has some strategic advantages compared to Scala as it is pushed by both JetBrains (the makers of IntelliJ) and Google (Kotlin is the language to-go for Android development) which allowed it to quickly gain traction. And it's a great language for sure. But similar to Scala, I don't believe that it will replace Java.
When switching from Java to another language, there are always issues. Some things are just not working as they do with Java, some things are not compatible, some tools are not available. Whatever it is, this results in less people either want to or succeed at switching.
So the next time you'll hear news like "Mega Corp. uses the new XYZ language" doesn't mean the whole company does. Maybe it's just one or two teams of a 100.000 employees. When a new language has "that great new feature" that Java doesn't have, it doesn't mean it can easily replace Java, the JVM, the community and Java's tooling.
So why is Java so successful?
In my opinion, it is the result of a couple of different factors:
- The language is relatively easy to learn and has a similar Syntax as C and C++
- The language is relatively stable, backwards compatible (Java 9, oh, Java 9)
- It is still able to adapt to new paradigms and technologies
- The JVM is a pretty damn fast runtime (see above)
- A lot of large companies are running their business on it which simply means: Job opportunities (see above)
- You'll virtually find any problem already solved as an open source library with licenses that allow commercial use
- The tooling is pretty great
The Future
So after looking at the status quo, let's have a look at the future. There are a lot of promising projects that are planned to be included in one of the next releases.
There are already a couple of in depth articles, so I will just briefly mention them here.
Loom
In my opinion, Project Loom is one of the most game-changing additions to the JVM and the language. It might appear to be rather uninteresting at first glance: Loom will bring "Fibers" aka. light-weight threads to the JVM. So why bother?
Unlike threads, you can run millions of Fibers, which have a low memory footprint, on a single core. Using Fibers, you can build continuations and tail-call optimizations which in turn allow to build non-blocking code that looks synchronous but does not block a thread. That means no code cluttered with chained callbacks or observables as it is common in e.g. vert.x or RxJava. I've written about it here:
https://dev.to/stealthmusic/dont-drink-too-much-reactive-cool-aid-20lk
Graal
Graal is another candidate for a game changer, in my opinion. Graal is actually not a single "thing". There is the GraalVm compiler that implements the new compiler extension API of the JVM to replace the existing JIT compiler with a JIT compiler written in plain Java. Then there is GraalVM Native Image that allows to compile Java code to a native binary which can drastically reduce memory usage and increase startup time of an application from seconds to milliseconds.
Although this sounds amazing and you can already try it, it is still in an early phase. I tried it myself and it was far from being production-ready or even just easy to use. It doesn't play well with frameworks or library that use reflection a lot (Spring, Hibernate). Without further insight, Graal will compile Spring Boot application with JPA to a native image with a fall-back work-around that simply bundles and runs the JVM and JDK within the image which doesn't give you the above advantages.
There are frameworks like Micronaut and Quarkus popping up that allow to leverage the full potential of native image though and I know that the Spring team is also working hard to get it working with Graal.
This might allow to use Java applications in areas where golang currently shines and fast a start-up and low memory usages is a must.
Amber
Project Amber brings data classes and sealed types to Java. It is a language feature and attempts to reduce the boilerplate code that is needed when created a POJO: Some fields, getters, setters. It will allow you to write something like record Point(int x, int y) { }
.
The features that Amber brings will also make it easier to implement pattern-matching.
There are a couple of ideas to pattern-matching. The first was switch expressions which has been released as a preview with Java 12 that allowed to directly assign the switch expression result to variable e.g.
Pattern matching in instanceOf will make it easier to work with unknown types and render type casting ofter an instanceOf
obsolete.
Then there is object deconstruction that allow to extract parts of an object or list into into its components:
int eval(Node n) {
return switch(n) {
case IntNode(int i) -> i;
case NegNode(Node n) -> -eval(n);
case AddNode(Node left, Node right) -> eval(left) + eval(right);
case MulNode(Node left, Node right) -> eval(left) * eval(right);
};
}
This replaces a lot of code clutter that would be necessary to implement the above.
And what would be really cool is pattern matching in methods (not sure if this planned):
int multiply(0, int b) { return 0}
int multiply(int a, 0) { return 0}
int multiply(int a, int b) { return a * b}
Valhalla
Project Valhalla attempts to allow immutable (great for concurrency) reference-free objects. An array e.g. is currently a list of references to its values instead of a list of the values itself. It will also allow to use primitive types (such as int
e.g.) as generic types. E.g. List<int>
instead of List<Integer>
.
Conclusion
So, to conclude, I honestly don't think that Java is dead. It has an active community, a rich ecosystem including tooling, a ton of libraries and frameworks, it is able to adapt and evolve while being backwards compatible (mostly) and it is still widely used in the industry.