Java 16 is out and you’re stuck with Java6 ? here is what you’re missing out

kommradHomer
19 min readMay 16, 2021

--

Thank you BellSOFT

Does one need to keep up with the new features coming with the hemorrhage of many Java versions day-by-day, especially since the new 6-month cycle starting with the release of JDK9 ? Probably not. I’ve spent a major share of my career coding Java 6 (and some Java8) and recently I’m moving to a new position as a Senior Java Developer. And guess what ? I’ll be coding Java6 and Java8 (at least for the first phase).

But one should take a look and see what’s going on , right? Java 6 to Java 16 means 10 releases while a few of the releases have colossal feature sets and changes , compared to others. (trivia:Java6 has so much under-the-hood performance improvement over Java5 , but almost nothing visible to a developer).I’ll try to write about the features that I find interesting or important or simply changes the syntax too much that you cannot understand the code otherwise, rather than listing all the JEPs(Java Enhancement Proposal).

From Java9 forward, I will be referring to the features that were “introduced” in that Java version , rather than the version they were added to the standard library. For example, the new Http client was introduced in Java9 and added to the standard library in Java11 and I’ll be talking about it on Java9.

What’s new in Java 7?

Java7 is the first java release from Oracle (hence making Java6 the last release from SUN). Java8 must be thousand folds more popular and in use than Java7 , so most devs would believe that all these differences between 6 and 8 must be introduced with 8 , but there are many features that are so basic and popular , introduced in Java 7

Switch on Strings (Java7)— Yes . Before Java7 , you had to use an integer for switch clauses. But this actually is a syntactic sugar, as the resulting Java byte-code is exactly the same. Something really useful and intuitive for sure!

Diamond operator <>(Java7)- the diamond operator can save you some typing of Types. Not much , but IDE does it automatically for you , so It’s welcome

Multiple catches on try-catch(Java7) — instead of using many catch clauses , one above the other , we can use many of them , seperated by an “|” operator , if they’re sharing the same handling code, of course

AutoClosable Interface and try-with-resource statement(Java7)- This saves you from dealing with many many nested try-catch-finally blocks, which are needed for properly handling the graceful closing of resources. We are talking about closing a Buffer that we opened , or closing a connection that we obtained from a collection pool , etc.. In the example below , you don’t need to deal with any logic for closing the FileOutputStream fs

File IO API nio (Java7)- This API seperated the functionality about Files and Paths . Things like creating a file or folder Path by simply listing the nested folder names ((“path”,”to”,”my”,”file.txt”)) or traversing the files or folders in a folder via DirectoryStream.

And It also brought some new features such as symlinks and File attributes

What’s new in Java8 ?

Java8 is, by far, the most used version by %75 of developers using it regularly . And as a release, It came with a HUGE set of features and performance enhancements. Many of the features introduced were deeply changing the way we code Java. So deeply that , when you first see a Java code that has utilized these new features , there’s a good chance you won’t understand what you’re looking at.

With the new release cycle started with Java9 , Java8 was announced as a LTS and also a “special” release , in terms of licencing and support.

jetbrains dev ecosystem

lambda (λ) functions(Java8)- Lambda statements are probably the most famous feature coming with Java8. It’s not much like what we are used to: more of a Functional Programming thing. A lambda statement is basically a nameless method and there are many forms of it. In many cases, it helps you code less. And it comes really handy and fundamental , with the use of Stream API that we will soon talk about.

There are 4 types of lambda expressions: Classic (prettiest of them all) , Typed , Multiline and within-closure

One (and probably not only) negative thing to note is that, these are methods with no names. So , to understand what It’s actually doing, you need to read that whole code block.IMHO, If you’re doing so many things in a lambda expression , probably you’re doing something wrong, or simply unreadable.a bad smell, if you will.

You can read a lot more about lambda expressions in this Lambda QuickStart page, actively guiding you about how to adapt this approach as well.

Interface default methods(Java8)- There were many changes targeting the existing APIs and many more were needed for the integration of these Functional programming features in the language, one of them was the need to find a way to add “not implemented” methods in Interfaces. Shortly put, a defaultmethod in an Interface , is a method that you’re allowed to not implement.

Method references (::)(Java8)- double-colon operator, Method reference, is a shorthand notation of a lambda expression to call a method. They have better readability , so are advised to be used wherever they can replace lambda expressions. They are pretty intuitive and easy to use.

There are 4 flavors to method reference ,but all share the same trait: the double-colon operator separating the class name(or variable name) and the method name.

Date-Time APIs(Java8)- Before Java8, the default support for date and time manipulation was horrible. You needed hundreds lines of not-so-trivial codes to do something so straightforward and simple. The design was lacking , the thread safety was nowhere to be found and and TimeZone handling required a great deal of mastery.(The dreadful Calendar c=Calendar.getInstance();)

Many of us were seeking refuge in joda time library as a date and time library and It became a de-facto standard, prior Java8. And Classes like FastDateFormat for thread-safe formatting and parsing. For Java8 ,the developer of Joda-Time library (Stephen Colebourne) joined forces with Oracle and implemented APIs that are so similar to Joda time , and as intuitive as them.

  • seperate APIs for Date and Time
  • seperate packages for Local and Zoned Dates
  • all immutable and thread-safe
  • simple functions for time arithmetics , timezone conversions , Instants, Durations , Chrono Units

Stream API(Java8)- Stream API streams are “..wrappers around a data source, allowing us to operate with that data source and making bulk processing convenient and fast..”. They have nothing to do with the IO operation streams. And a stream does not store any data , and does not let you modify the data you are streaming. (src)

This API resides at java.util.streampackage and provides functionality over a Stream of Elements , in fashion with functional-style programming, like many kinds of filtering , map-reduce transformations and such.

With chaining many Stream operations , we create a Steam pipeline. And a Stream pipeline consists of 0 or more intermediate operations(processing elements and creating a new Stream to continue with) and exactly 1 terminal operation(processing the elements and marking the Stream consumed) called finally.

Some of the most notable Stream Operations are such:

  • forEach() — Simply looping over all the elements and running the given function on each of them. This is a terminal operation, where such an operation is one that cannot be followed with another Stream Operation.
  • map() — This operation is for applying a function on each element and creating another stream for following up with other Stream operations.The resulting stream type might be completely different from the original one.(map of map-reduce)
  • flatMap() — If your Stream elements are not singular , like Collections of objects , you can flatten them into a Stream of singular elements with this operation. Another word could be “unwind”. For example , If your Stream elements are “List<String>” and you actually want to do something for each “String” in those lists , this is your operation.
  • filter() — A little similar to map operation , this operation , using a predicate , filters out the non-matching elements and creates a new Stream with the matching elements
  • collect() — For getting results out ,once you are done with processing all the elements , you can use this operation to store data in a Collection.You can easily guess that this is another terminal operation.

You can learn a good amount about Java8 Stream API in this 5-video series by Marco Behler , linked below.

One can have quite some fun as the examples are mostly about POTUS Donald Trump’s wives and kids :)

Bonus subtitle on Streams- Parallel Streams

Java language is neither the easiest nor the prettiest , when it comes to Multithreading or parallelism. But the Stream API is helping a little , at least with not so complicated scenarios.

We can run our Stream Pipeline iterations in parallel , by simply calling parallelStream() as the start of our Stream Pipeline or by calling parallel() on a stream object. Our operations will run on as many threads as the number of our cores, for the default implementation decides the number via “ForkJoinPool.commonPool(), which has a default size equal to one less than the number of cores of your CPU.” This number can be adjusted by providing a custom ForkJoinPool() object.

It sounds too good to be true. So what’s the catch? not much . There are 3 things you need to consider, before running your Stream Pipeline in parallel:

  • statelessness — state of one element does not affect another element
  • non-interfering — data source is not affected
  • associative — the result of the process should not be affected by the order of executions, as no order of elements is guaranteed , unlike sequential processing.

Another thing you should consider is the amount of your elements. There’s no benefit in calling parallel streams for little amounts of data , as the parallelism has its own book keeping overhead costs.

What’s new in Java9?

with Java9 , for the very first time , after 23 years, there was a removal of deprecated APIs.And Java9 was the start of 6-month release cycles, announcing us to expect Java10 in March 2018.

JShell (Java9)— With JShell, just like a python or ruby terminal , you can use a JIT compiler. I have never tried , as I never needed to. But can come handy for quick prototyping.

Collection Factory Methods(Java9) — One of my favourite features. Say goodbye to ugly static blocks or inner classes or row-after-row of data for initializing Collections! With methods such as List.of(),Map.of(),Set.of() you can simply provide all your data and let Java parse them in to tuples or single elements as necessary and initialize your Collection for you

new HTTP Client API(Java9) — A modern and simple HTTP client can save you from importing the Apache HTTP Client lib. A better design , HTTP/2 support , performance and security enhancements. A pretty good addition to the standard library, considering the apache http client becoming a de-facto standard.

G1 Garbage Collector(Java9) — Something under the hood, but worth mentioning. Even though it was out since JDK7u4 , it improved so much and became the default GC, starting from Java9. G1 Garbage collector is more adjustable and favors low latency over throughput.

What’s new in Java10?

container aware JVM(Java10)-Java10 JVM is more aware about running in a container. What this means is that, It’s looking up to the container, rather than the actual machine, for resources. This awareness helps with solving confusions about CPU counts or process ids

var keyword(Java10) — Java is still a Statically Typed language. Now that the question is out of the way, what Java10 compiler does is that It lets you use the var keyword and infer to the Type of the variable automatically. This is only available on Local variables but helps a lot with typing less and code readability. And It’s intuitive and easy to use. Such a nice addition.

The var keyword simply helps with the automatic type inferring and It’s done only once at the creation of the object that will be stored. So if you have a var X that holds an Integer, then It’s going to be an Integer variable so forth, you cannot assign , say , a String to that variable X.

In the case of Inheritance , a variable declared with var is always the type of the initializer . For Example , if classes DOCTOR and ENGINEER are subclasses of WORKER , a variable declared with var for holding a new Doctor(), that variable will be typed as DOCTOR, not a WORKER.

A few Other things to not about var keyword:

  • cannot use for supplying a null such asvar x=null; as It would be impossible to infer the type
  • cannot use for arguments on a method declaration , as It would be impossible to infer the type
  • cannot use with lambda expressions , as the expression would need an explicit target type

GraalVM(Java10) — A new Java VM , by Oracle Labs, based on HotSpot/OpenJDK . Another Java VM , but why ?

  • Fast (?) — They claim that they are running Java and Java-like(scala,kotlin etc) faster “..due to its ability to remove costly object allocations in many scenarios..”
  • Polyglot . It’s not Just for Java. You can run NodeJS apps, Ruby, R , python. Even a MySQL (interesting , to say the least). Truffle is the name of the Language Implementation API for GraalVM, which makes this polyglots possible
  • Standalone mode — GraalVM can pack your application in a native package so that It can run almost instantly

More about the GraalVM in this video below and on graalvm.org

BONUS CONTENT ON GraalVM-Twitter

Twitter running GraalVM on Production

What’s new in Java11? is Java still free ?

Java11 is a distinctive release for a few reasons. Starting with this release , Oracle JDK and OpenJDK are providing exactly the same functionality. And for doing so , some features were open-sourced and some were simply removed from Oracle JDK

  • open-sourced — some parts like Flight recorder and Mission control
  • removed — browser plugin support, JavaFX, Java Web Start

This is,sort of, a historic change because the resulting OracleJDK (from JDK11) cannot be used FOR FREE in Production anymore. A commercial support contract will be necessary. The whole work of modules on Java9 was a preparation for the clean-ups and these separate handling of binaries. If you want to use Java for free in production, you need to use OpenJDK binaries from https://openjdk.java.net

The clean up that was started with Java9 has accelerated to a new degree with Java11. The java.se.ee meta-module was removed, which contains packages like java.corba,java.transaction,java.xml.bind and java.ws.Also the dreaded Nashorn Javascript engine was finally depracated.

EpsilonGC(Java11)— A garbage collector that does no Garbage collecting at all. This GC was proposed and implemented by RedHat for JDK11, aimed at JVM researchers and maybe some cutting-edge high performance applications that are designed to run in environments where they terminate before they would use all the heap space. Now one wonders , How much time or effort does It take to implement a GC that does no garbage collection ?

single-file program and shebang(#!) support(Java11) — with Java11, one can simply run a Java Class without compiling it.user@pc:-$ java MyClass.java It’s compiled implicitly and you still need a public static void main() in that Class though. This might help a lot with newbies and it does look neat.

Also you can simply place a shebang at the top of your Class file and just execute the file, to the same effect as running it like a bash file

new I/O methods for null(Java11) — now Java11 has Its own “/dev/null” for reading,writing and input or output streams

new String Methods(Java11) — There are some new String methods such as:

  • lines()— returns a stream of lines from the string , that’s if the string contains lines
  • repeat() — for repeating a string
  • strip() — like trim , but has a better definition of “white space”
  • isBlank()-tells you if a string is blank , even if not empty

what’s new in Java12?

Enhanced Switch Statements(Java12)-the good old “switch-case” is updated hugely , becoming a lot more developer-friendly and intuitive.The ulterior motivation of all these changes is moving towards Pattern Matching. 4 points of imporvement are made so far:

— Avoiding fall-through — Prior to Java12 , switch statements had a behaviour called fall-through: starting from the matching case, keep executing every code block until reaching a break; statement.

With the new “lambda-like” syntax of switch statements , you can type clearer code and avoid the need to use breakstatements. After the arrow , you can use a single expression or a code block in curly brackets

Switch statement with no fall-through

— Compound Cases — You can simply group your cases, use multiple cases, by separating them via Commas

Compound Cases

— Exhaustiveness check — A new check on switch statemens when an Enum is used : Exhaustiveness check. This control makes sure that your switch statement is covering all possible labels

Expression Form (Switch expressions)— The switch statement is a , wait for it… statement. There was no expression form of it before. Where an expression can be described as a “…“requests” that produce a value” and a statement is more of an “action”.

So , with the new expression form , we can simply assign the produced value to a variable, saving us from the trouble of typing the same assignment code for each label. This leads to massively better readability and less code.

Switch Expressions

Compact Number Formatting(Java12) — A great formatter for formatting a number in each Locale and language.Strangely I feel like I didn’t know that I needed this, before seeing It. You can see a nice example with many different Locales HERE

Compact Number Formatting

Teeing Collector(Stream API)(Java12) — Working just like the tee command on Linux .An advanced but useful addition to the Stream API. Prevents you from running the same stream pipeline twice in may use cases.

“..a composite of two downstream collectors where every element passed to the resulting collector is processed by both downstream collectors, then their results are merged using the specified merge function into the final result. ”(FROM DOCS)

Files.mistach()(Java12) — A new method in Files class , telling you the position of the first byte where 2 given files differ. It returns -1 if the files are identical. Would this be faster than MD5SUM for checking exactness? I don’t know.

G1 Garbage Collector Enhancement(Java12) — the G1 that was default GC since Java9 , started “giving back” the unused memory to the OS. This is huge news in some cases and useful in any case.

what’s new in Java13?

Text Blocks(Java13) — Finally , we can store multi-line texts without several +s , \ns and escape characters and the whole loss of formatting and indentation.So useful while storing a JSONObject or a SQL query, for an example of every day usage.

A Text Block , once created , can be used just as any other String. To create a Text Block , we need to start with 3 quotation marks followed by a new line and end it with 3 quotation marks. But where you place your “ending” quotation marks matters, for the indent calculation.

Java13 Text Block

the way indentation works is a little tricky

  • every white space is counted as 1. so in your IDE , you might be seeing a line starting with 5 tabs(let’s say your tab is 4 spaces) more indented than another line starting with 7 spaces , but the actual outcoming Text block will result with the 2nd row being more indented than the first one
  • the minimum indentation of the minimum row is subtracted from all rows before the resulting indentation . Let’s say line1 has 5 spaces , line2 has 3 spaces and line3 has 6 spaces. In this scenario , every line will have their first 3 spaces removed while calculating the final indentation. So line1 will be indented with 2 spaces , line2 will not be indented and line3 will be indented 3 spaces
  • if the ending quotation marks have their own line , their indentation is also accounted for , during the calculation of indentations.

yield keyword on Switch Expressions(Java13) — in Java12 , the keyword for returning a value was “break” , like case Monday: break “god dammit";.From Java13 forward, we should be using the yield keyword instead, as case Monday: yield “god dammit";. A mixed usage of the arrow syntax and the yield keyword are also supported

mixed usage of yield keyword and arrow syntax

Dynamic CDS Archives(Java13) — The Class Data Sharing (CDS) improves startup performance by creating a class-data archive once and reusing it so that the JVM needs not to recreate it again.This is a crucial feature in environments where many JVMs are created and destroyed repeatedly, and/or where the system is billed by the running time.

This feature can cut down the start up times in half easily, even in minimal examples. The effect is more dramatical when you use something like Spring Boot.

##CREATING A CDS Archive
$ java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
##REUSING A CDS Archive
$ java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

ZGC enhancement(Java13) — Similar to the enhancement on G1 GC in Java12 , with Java13, ZGC can uncommit unused memory

What’s new in Java14?

helpful NPEs(Java14) — The dreaded NullPointerException finally tells you WHAT THE HELL IS WRONG! by telling you which variable is null. So you won’t need to do extra coding for logging to figure it out.

Helpful NullPointerException

Records(Java14) — I don’t know how many times I’ve written my own and broken implementation for the need of a “record” or “tuple” in Java. Finally with Java14, comes Records. records are a new kind of type declaration. A record is a restricted form of a class, like enum

  • a final class . not abstract
  • all of Its fields are final
  • constructors , public get()s , hashCode(), toString() methods automatilcally created during compile time

Whenever you need a way to carry over data, you can simply create a record and work with it. You can simply declare a record and use it in the next line. So intuitive and useful

a record type just declared and used instantly

Boilerplate code comparison

Below is a comparison of a “data carrier” example Person class before Java 14

//BEFORE JAVA14
public
class Person {
private final String name;
private final String gender;
private final int age;

public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}

public String getName() {
return name;
}

public String getGender() {
return gender;
}

public int getAge() {
return age;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name) &&
Objects.equals(gender, person.gender);
}

@Override
public int hashCode() {
return Objects.hash(name, gender, age);
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
'}';
}
}

Created on Java14 : record Person(String name,String gender,int age) {}

Pattern matching for instanceof(Java14) — instead of “check first-cast later” behaviour , with pattern matching , If an object is instanceof what we are looking for , It’s automatically casted to that type and assigned to a bind variable. We can simply use it.

instanceof pattern matching

what’s new in Java15?

This release is dominated by the news of Garbage Collectors: ZGC and Shenandoah GC are finally product features. But G1 is still the default Garbage Collector. Speaking of garbage, the Nashorn JS engine and jjs tool are removed by this release finally.

Sealed Classes(Java15) — With sealedkeyword, we can restrict the possible subclasses of a class or interface.

Sealed Classes

The sealed class must have subclasses and Every permitted subclass must choose a modifier (sealed, non-seal, final) to describe how it continues the sealing initiated by its superclass

Types of continuation for Sealed classes

When you open a subclass of a Sealed class with the keyword “non-sealed” , anyone can extend that class , as usual.

What’s new in Java16?

Vector API(Java16) — Java supports auto vectorization for arithmetic algorithms , whic means the JIT compiler transforms some scalar operations to vector opreations , when It sees fit. But the developer has no control over this.

With the new Vector APIs , developers can perform vector operations explicitly and make better use of multiple core capabilities.

A simple addition,squaring and negating operation on 2 float vectors — https://www.mscharhag.com/java/vector-api

I thought that I would easily create this post as a summary of what I’ve been watching, listening and reading. But It turned out to be a lot more time consuming and I ended up revising twice the time I had spent earlier. This must be my longest post so far. Kinda proud.

It’s obvious that the listing grows thin as we approach the end . Does It have something to do with Covid-19 ? I say why not. The last 2 releases were largely about making the final touches for some major points and placing them in the standard version.

I feel heartbroken about the fact that I won’t be able to use these neat features , and new knowledge , in my new position. But who knows , maybe I can become a voice to be heard and argue about the importance of these new features and Garbage Collectors as a forcing reason to updating the existing infrastructure step-by-step…

--

--

kommradHomer
kommradHomer

Written by kommradHomer

proud seeder of 146.5GB The.Lord.of.the.Rings.Trilogy.1080p.Extended.Complete.Bluray.DTS-HD-6.1.x264-Grym

Responses (7)