There’s always been a considerable level of criticism against Java from a big sector of our industry; this criticism has been mostly focused on Java’s verbosity and the amount of boilerplate code it generates in many cases without need. It is quite common to find opinionated developers emphasising that there will be no future for Java in our sector.
Although I’ve always liked Java, I couldn’t say that these allegations are wrong; it’s indeed true that Java’s verbosity and its amount of clutter could become very annoying in multiple occasions. Although most of the times we have to accept that we don’t live in a perfect world and in most of the cases we have to accept the lesser of two evils. So yes, Java wasn’t perfect, we all know that, but the main question is why nothing was done before to address these concerns.
In my personal opinion, the only reason why changes took so long is because there wasn’t enough competition for Java, things were right as they were. Java language was dominating the market probably due to the lack of serious competitors and due to the big efforts made by Sun first and then Oracle afterwards.
The strong type safety provided by Java and some of its characteristics as a well-structured language made it a very popular language for big projects; by using Java it’s generally more difficult to get things really out of hand. Also one of the main characteristics of Java, being a multi platform language which runs on its own virtual machine, made it a perfect match for many organisations.
If you add its inherent capability of performing automatic performance optimisations through its famous JIT compiler, something that minimises in many cases the effects of badly-written code, then you have a pretty solid set of reasons to use Java.
But then what happened? What happened is that new languages able to run in the same JVM as Java were introduced into the market; languages that were eliminating some of the biggest annoyances in Java and offering a nicer environment to developers with quite a flat learning curve in some cases.
Before we continue let’s recapitulate and take a brief tour through the history of JVM languages!
History of JVM languages
Once thing I’d like to clarify before we start, is that I’ve skipped some of the existing JVM languages mainly because they never got enough traction to be considered candidates to be used widely in our industry. Having said that, let’s kick off our quick tour thorough JVM languages history!

To start with our tour we have to start with Java of course, the oldest and most popular language in the JVM world.
Java was officially released in January 1996, so it’s been around for twenty-four years already; not bad, eh? Initially Java was a purely imperative language following a purely object-oriented programming style; also being a strongly typed language.
Java’s syntax is similar in some way to C++ and C languages, but it’s considered an improved version because it’s much easier to write code with Java than C or C++. On the other hand, we have that the biggest argument among its detractors is its verbosity.
The second JVM language that was released was Groovy; it started being around since 2003, although it’s first official and standardised version 1.0 didn’t come up until January 2007. Groovy had the benefit of being able to be used as a scripting language as well. Groovy is a dynamically typed language, so type checks occur at runtime; this is one of the reasons why some developers don’t like Groovy. You write your code in Groovy, it looks correct on compilation time but then on runtime is when you realise that there’s something wrong.

A very popular language for a few years came up next, we’re talking about Scala. Scala was officially released in 2004 and it brought a new programming model to the JVM world with functional programming and its declarative approach. We could affirm that Scala was the first to bring this concept of immutability that we’ve talked about before, so it has done very good things for the Java transformation. On the other hand, Scala detractors don’t like it due to its complex grammar and in general low readability.

The next language to make its appearance in the JVM world was Clojure, a purely functional language that is becoming quite popular recently but it first appeared in 2007. Clojure is a LISP based language characterised by its simplicity and the use of pure functions. Among its drawbacks we could mention that it’s dynamically typed (same as Groovy) and the learning curve is much steeper, as its syntax is completely different from other JVM languages. There are a couple of good books that you should read if you’re interested in learning Clojure: “The joy of Clojure” and “Programming Clojure: 3rd Edition“.

And lastly but not least we have Kotlin! Kotlin was first released in February 2016 and since then it hasn’t stopped growing in popularity. It was designed by the company JetBrains with one clear goal: eliminate all the most popular Java problems. In the way it’s been designed it has kept all the good things about Java but at the same time eliminating the majority of its problems; that’s why it’s becoming so popular and many consider that it could defeat Java in the next few years.
If you want to know more about Kotlin (I encourage to do so, as it’s a great language), I’d recommend that you read the book “Kotlin in Action”, a fantastic book to start with Kotlin for Java developers.

So this are the most important JVM languages, we have skipped some others that are not so popular but we could mention some of them: Jython, JRuby, Ceylon, Fantom, etc. You can check the whole list of the existing JVM languages here.
One thing that we could notice is that Java didn’t have much competitors in the first eight or ten years but since then it started having some competition; so is having competition good or bad?
Benefits of increased competition
As we mentioned earlier, Java hadn’t changed too much in its early years probably because there was no need for it; the language was widely used and very popular despite of being far from perfect.
But then new competitors showed up, more modern languages that were bringing new features and solving some of the pain points that Java developers had been suffering for a long time.
For instance, let’s look at Scala language; Scala’s popularity was increasing since 2009, developers were welcoming this new functional style that allowed them more flexibility and also write parallel code safely and easily. We can see this trend in the following Google Trends graph:

What was Oracle’s reaction to this new trend? Java Lambdas and Streams were released in 2014. I think we can all agree that at that point was when Java made its biggest step to defeat Scala; everyone who currently works in the industry can feel that lose of steam that Scala has been suffering in the recent years.
One more benefit in having more competitors in the JVM world is the continuous improvements that JIT compiler and the JVM itself are experiencing. Now there are much more people interested in having an optimised JVM and improved performance optimisations. So competition has been a good thing for everyone!
The last competitor to appear in the arena has been Kotlin, and Kotlin has been very important because in some way it has shown Oracle the way to go forward. Kotlin has shown that it’s possible to keep the good parts of Java but creating a more concise and fast to code language.
If we look at Google Trends to see how popular has Kotlin been in the last few years this is what we have:

So it seems that Kotlin became quite popular fairly quickly but it seems to be settling down in the last couple of years.
Oracle has taken good notes of the industry’s reactions with regards to Kotlin and if you take a look at the JDK 15 release notes, you can see that some of the Java new features are basically copies of what Kotlin had changed. For example, the new Java records, the new text blocks (multi-line string with triple quotes) or the new switch statement; which is more or less a copy of Kotlin when statement. You can take a look at JDK 15 release notes here.
All of this we’ve talked about is what I call “The Kotlinisation of Java”; by becoming its stronger competitor in its history, Kotlin has shown Java the way to go. From my point of view Kotlin has been the only language I’ve seen that could overcome Java as a leader in our industry.
The “Kotlinisation” of Java
Some of the upcoming Java features are going to be a massive improvement for Java in terms of readability and in terms of improving one of the main weaknesses in Java, its verbosity. We could affirm that they all have a suspicious similarity with some Kotlin features.
Please keep in mind that most of these features are feature previews, what means that if you install JDK 14 or JDK 15 when it gets released, you won’t be able to use them by default.
Java feature previews are new features that are introduced in a release but are disabled by default; they’re included in the release just to gather feedback from the community of developers, so they’re still subject to changes and that’s why it’s not recommend to use them in production code.
To enable them at compilation time you’d have to do the following:
javac --enable-preview --release 14
If you want to enable them at runtime you’d have to run the following:
java --enable-preview YourClass
Of course, you can also enable them in your IDE, but be careful to not enable previews by default in all your new projects!
Let’s take a look at those changes that are going to have a bigger impact on our coding with future versions of Java!
Java records
Java records are a feature that many of us have been demanding for a long time; I guess you’ve been in the same situation multiple times, when you reluctantly have to implement toString, hashCode, equals and also getters for each existing field (I’m assuming that you’re no longer using setters, and you definitely should not; remember when we talked about immutability in the article “A new concurrency model in Java”).
Kotlin provides data classes to solve this problem and Java is intending to do the same by releasing the record classes; something that Scala also has with its case classes.
The main purpose of these classes is to hold immutable data in an object. Let’s take a look at how much better will it be in Java by looking at an example. This is how much code we’d have to write to be able to instantiate and compare our Employee class:
public class Employee {
private final String firstName;
private final String surname;
private final int age;
private final Address address;
private final double salary;
public Employee(String firstName, String surname, int age, Address address, double salary) {
this.firstName = firstName;
this.surname = surname;
this.age = age;
this.address = address;
this.salary = salary;
}
public String getFirstName() {
return firstName;
}
public String getSurname() {
return surname;
}
public int getAge() {
return age;
}
public Address getAddress() {
return address;
}
public double getSalary() {
return salary;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
Double.compare(employee.salary, salary) == 0 &&
Objects.equals(firstName, employee.firstName) &&
Objects.equals(surname, employee.surname) &&
Objects.equals(address, employee.address);
}
@Override
public int hashCode() {
return Objects.hash(firstName, surname, age, address, salary);
}
@Override
public String toString() {
return "Employee{" +
"firstName='" + firstName + '\'' +
", surname='" + surname + '\'' +
", age=" + age +
", address=" + address +
", salary=" + salary +
'}';
}
}
And also the Address object it contains:
public class Address {
private final String firstLine;
private final String secondLine;
private final String postCode;
public Address(String firstLine, String secondLine, String postCode) {
this.firstLine = firstLine;
this.secondLine = secondLine;
this.postCode = postCode;
}
public String getFirstLine() {
return firstLine;
}
public String getSecondLine() {
return secondLine;
}
public String getPostCode() {
return postCode;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
return Objects.equals(firstLine, address.firstLine) &&
Objects.equals(secondLine, address.secondLine) &&
Objects.equals(postCode, address.postCode);
}
@Override
public int hashCode() {
return Objects.hash(firstLine, secondLine, postCode);
}
@Override
public String toString() {
return "Address{" +
"firstLine='" + firstLine + '\'' +
", secondLine='" + secondLine + '\'' +
", postCode='" + postCode + '\'' +
'}';
}
}
That’s a lot of code for something as simple, isn’t it?
Let’s take a look now at how will it look like with the new Java records:
public record EmployeeRecord(String firstName, String surname, int age, AddressRecord address, double salary) {}
And also our Address class again:
public record AddressRecord(String firstLine, String secondLine, String postCode) {}
This is exactly the same we wrote earlier with so much code, you will have to agree with me on this; this is amazing! The amount of code we’re going to save and how much simpler it is!
Let’s see now what the differences are in the new switch statement!
Improved switch statement
The new switch statements in Java solve some of the inherent problems of using switch statements in Java. Switch statements at this moment should always be avoided because they’re very error-prone and lead to code duplication; currently it’s very easy to leave a case uncovered for example.
With the new switch statements that’s solved, because it won’t compile if our switch statement doesn’t cover the whole range of the domain that belongs to the type we pass in to the switch.
To explain this with an example we’re going to create a DayOfTheWeek enum in Java:
public enum DayOfTheWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
Having that, our switch is going to tell us what position in the week corresponds to that day. Let’s see first how can we currently do this using Java 11.
final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;
int position = 0;
switch (dayOfTheWeek) {
case MONDAY:
position = 1;
break;
case TUESDAY:
position = 2;
break;
case WEDNESDAY:
position = 3;
break;
case THURSDAY:
position = 4;
break;
case FRIDAY:
position = 5;
break;
case SATURDAY:
position = 6;
break;
case SUNDAY:
position = 7;
break;
}
System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");
Using the current switch statement we’d have to make use of a variable and also if we miss one of the days of the week, our code will compile perfectly. This is one of the problems of switch statements; it’s very error-prone.
So how does Java 14 improves the situation? Let’s see quickly how:
final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;
int position = switch (dayOfTheWeek) {
case MONDAY -> 1;
case TUESDAY -> 2;
case WEDNESDAY -> 3;
case THURSDAY -> 4;
case FRIDAY -> 5;
case SATURDAY -> 6;
case SUNDAY -> 7;
};
System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");
You will be able to see very quickly that the new switch statements can be used as an expression, not only as a statement.
The result is more concise and expressive; that would be enough to convince many of us for using them, but one of the main improvements is that now switch statements won’t compile if we don’t cover all the cases in our switch. It will show us the following error for example:
Error:(9, 24) java: the switch expression does not cover all possible input values
From now on it’ll be impossible to miss a case in our switch statements; that’s awesome, isn’t it?
This is very similar to Kotlin when statements, you can read about them here.
Let’s take a look now also at the new text blocks!
Text blocks
Have you ever moaned about how ugly and difficult was to assign a big blob of JSON to a variable in Java? Java will introduce multi-line strings that you can define by wrapping them between triple quotes; when this feature gets officially released it’ll be much easier to define long strings in multiple lines.
Let’s take a look at the differences between the two modes. At the moment if we want to store a formatted JSON in a variable it looks as ugly as this:
final String text = "{\"widget\": {\n" +
" \"debug\": \"on\",\n" +
" \"window\": {\n" +
" \"title\": \"Sample Konfabulator Widget\",\n" +
" \"name\": \"main_window\",\n" +
" \"width\": 500,\n" +
" \"height\": 500\n" +
" },\n" +
" \"image\": { \n" +
" \"src\": \"Images/Sun.png\",\n" +
" \"name\": \"sun1\",\n" +
" \"hOffset\": 250,\n" +
" \"vOffset\": 250,\n" +
" \"alignment\": \"center\"\n" +
" },\n" +
" \"text\": {\n" +
" \"data\": \"Click Here\",\n" +
" \"size\": 36,\n" +
" \"style\": \"bold\",\n" +
" \"name\": \"text1\",\n" +
" \"hOffset\": 250,\n" +
" \"vOffset\": 100,\n" +
" \"alignment\": \"center\",\n" +
" \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" +
" }\n" +
"}} ";
On the other hand, when new text blocks get released it’ll be as easy and clean as this:
final String multiLineText = """
{ "widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {\s
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
""";
I think that’s much better, don’t you agree? This is also something supported in Kotlin, as you can find in its type definitions here.
So we’ve seen that Java is “inheriting” many of the solutions to its own problems from one of its competitors: Kotlin. We don’t know if this time Oracle has reacted right in time to combat the rise of Kotlin or if maybe it comes too late; personally I think that Java is taking the right steps forward, even if these changes were triggered in some way by its competitors and it might come a bit late.
As mentioned earlier, if this article has triggered your interest in learning Kotlin language, I’d recommend that you read “Kotlin in Action”; a very good book to start with Kotlin for Java Developers.
If you are interested in learning more deeply about any Java topics, we recommend the following books:
Conclusion
I think competition has been the best thing it has ever happened to the Java language; I have the impression that otherwise Java would have rested on its laurels. Also Java competitors have shown that a different way of programming was possible, showing the way to go forward and avoid staying in an old-fashioned and rusty way of writing code.
The changes I’ve been seeing in Java recently, with all the upcoming features and improvements, are making a stronger Java than ever; a language adapted to the current times, a language that wants to evolve and forget about the traditional way of doing things: a new future for Java!
I really hope you’ve enjoyed this reading and I hope I can see you soon again! Please follow me if you like my articles to get notified the next time a new article gets published!
Thank you very much for reading!
One comment