JAVA 7 vs 8 vs 9 vs 10 vs 11 vs 12 vs 13 vs 14 vs 15 vs 16 vs 17 vs 18 vs 19 vs 20 vs 21


1- switch with string- 

String a=”a”;
case “a”:sop(“f”);

case “b”:sop(“s”);

case default:


2-multi catch

Before java 7-


}catch(ArithmeticException e){

}catch(Exception e){


After java 7-


}catch(ArithmeticException | Exception e){


3- try with resources-

Before java 7-

FileOutputStream fo=new FileOutputStream ();
}catch(IOException e){

After java 7-

try(FileOutputStream fo=new FileOutputStream ()){

}catch(IOException e){

4-Underscore with variable

long a=2345_3456_9012_9774L; 
int a=6_345;
(just for better readability)

5-Type Inference for Generic Instance-

Before java 7-

Map<String, List<String>> anagrams = new HashMap<String, List<String>>();

after java 7-

Map<String, List<String>> anagrams = new HashMap<>();

6- java.nio.file package-

Better support for file I/O and for accessing the file system.
A zip file system provider is also available in JDK 7.



1-Functional Interfaces and Lambda Expressions-

@functionalInterface should be used on interface which have only one 1 abstract method.
– Lambda expression is a way to represent method implementation of functional interface.
Syntax –

Before java 8-

Runnable r = new Runnable(){
public void run() {
System.out.println(“My Runnable”);

After java 8-

Runnable r1 = () -> {
System.out.println(“My Runnable”);

2-Java Stream API for Bulk Data Operations on Collections-

-filter, sorted, toList, toSet, toMap, distinct, etc methods are included.

3- Default methods in interface

similar to non abstract methods, can be called without instance.

4- static methods in interface

static methods can be called on the name of interface.

5-forEach() method in Iterable interface


6- Java Time API Enhancements –

-addition of java.time package
-sub-packages java.time.format that provides classes to print and parse dates and times and provides support for time-zones and their rules.
-One of the useful class is DateTimeFormatter for converting datetime objects to strings.

7-Collection API improvements-

-Collection default method removeIf
Spliteterator– used to traverse elements sequentially or parallel.
-Map  replaceAll, compute, merge methods.

8-Concurrency API improvements-

ConcurrentHashmap- compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), reduce() and search() methods.


  1. JDBC-ODBC Bridge has been removed.
  2. PermGen memory space has been removed.


1- Interface private methods

so default methods can share some methods.

2- collection factory methods –

ex- li.listOf(“a”, “b”, “c”);


1- Variable type inference- so

var name= “kuldeep”;

is valid statement now.


1. Local-Variable Syntax for Lambda Parameters –

(x, y) -> x.process(y)
We’ll be able to write:
(var x, var y) -> x.process(y)

This expands Java 10 Local Variable Type Inference, that introduced a new syntax that reduces the verbosity associated with writing Java, while maintaining the commitment to static type safety.
In other words, you’ll be able to declare variables without having to specify the associated type.

2 – Other Changes in the existing classes:

A. New String Methods — 
strip(), stripLeading(),stripTrailing(),isBlank(),lines(),repeat(n)

B. Files Utility Methods-  writeString(), readString(), isSameFile()

C. HTTP Client(Standard) – The new API supports both HTTP/1.1 and HTTP/2. It aims to replace the legacy HttpUrlConnection class.


Switch Expressions –Classic switch statement:

File mismatch() Method – i.e. long mismatch = Files.mismatch(filePath1, filePath2);

Java Strings New Methods : indent, transform,describeConstable, resolveConstantDesc.

Pattern Matching for instanceof –The old way to typecast a type to another type is:

Raw String Literals is Removed From JDK 12.


1-The addition of text blocks in a preview phase – A text block is a multi-line string literal that avoids the need for most escape sequences.

2-A second preview of switch expressions –  There had been one in JDK 12, but a change is slated to be made: to yield a value from a switch expression, the break with value statement is to be dropped in favor of a yield statement.

3-Enhancements to the ZGC –  (Z Garbage Collector) to return unused memory to the operating system.

JAVA 14 – Important features –

1. Switch Expressions

Switch Expressions after staying a preview feature in the last two releases –Java 12 and Java 13 have finally attained permanent status in Java 14.

  • Java 12 introduced the lambda syntax for switch expressions thereby allowing multiple case labels for pattern matching as well as preventing fall-throughs which lead to verbose code. It also enforced exhaustive cases wherein a compilation error would be thrown if all the input cases aren’t covered.
  • Java 13, the second preview introduced yield statements instead of break for returning values from an expression.

Java 14 has finally made these features a standard now.

String result = switch (day) {            case "M", "W", "F" -> "MWF";            case "T", "TH", "S" -> "TTS";            default -> {                if(day.isEmpty())                    yield "Please insert a valid day.";                else                    yield "Looks like a Sunday.";            }         };System.out.println(result);

2. Pattern Matching for instanceof (Preview)

Ask any Java developer to show their codebase and you’ll a good use of instanceof conditions throughout the code. Specifically, an instanceof conditional check is generally followed by a typecasting.

Java 14, gets rid of this verbosity by making conditional extraction a lot more concise.

Before Java 14:

if (obj instanceof Journaldev) {  Journaldev jd = (Journaldev) obj;  System.out.println(jd.getAuthor());}

Java 14 Onwards:

if (obj instanceof Journaldev jd) {  System.out.println(jd.getAuthor());}

3. Helpful NullPointerExceptions

Null Pointer Exceptions are a nightmare for any developer. Previously, until Java 13, it was tricky to debug the infamous NPEs. Developers had to fall onto other debugging tools or manually figure the variable/method that was null since the stack trace would only show the line number.

Before Java 14:

String name = jd.getBlog().getAuthor() //StacktraceException in thread "main" java.lang.NullPointerException    at NullPointerExample.main(

Java 14 introduced a new JVM feature which gives better insights with a more descriptive stack as shown below:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Blog.getAuthor()" because the return value of "Journaldev.getBlog()" is null    at NullPointerExample.main(

Note: The above feature is not a language feature. It’s an enhancement in the runtime environment.

4. Records (Preview)

A record is a data class that stores pure data. The idea behind introducing records is to quickly create simple and concise classes devoid of boilerplate code.

Normally a class in Java would require you to implement equals()hashCode() , the getters and setters methods. While some IDEs support auto-generation of such classes, the code is still verbose. With a record you need to simply define a class in the following way.

record Author(){}//orrecord Author (String name, String topic) {}

Furthermore, we can add additional fields, methods, and constructor to the record in the following way:

record Author (int id, String name, String topic) {    static int followers;     public static String followerCount() {        return "Followers are "+ followers;    }     public String description(){        return "Author "+ name + " writes on "+ topic;    }     public Author{    if (id < 0) {        throw new IllegalArgumentException( "id must be greater than 0.");     }   }}

JAVA 15 – Important features –

  • Sealed Classes (Preview) – JEP 360
  • Pattern Matching for instanceof (Second Preview) – JEP 375
  • Records (Second Preview) – JEP 359
  • Text Blocks (Standard) – JEP 378
  • Hidden Classes – JEP 371
  • Remove the Nashorn JavaScript Engine – JEP 372
  • Reimplement the Legacy DatagramSocket API – JEP 373
  • Disable and Deprecate Biased Locking – JEP 374
  • Shenandoah: A Low-Pause-Time Garbage Collector – JEP 379
  • Remove the Solaris and SPARC Ports – JEP 381
  • Foreign-Memory Access API (Second Incubator) – JEP 383
  • Deprecate RMI Activation for Removal – JEP 385

1. Sealed Classes (Preview)

Sealed classes have been there in Kotlin since a while and Java 15 finally introduces this feature for better control over inheritance.

As the name suggests, Sealed classes let you restrict or permit class hierarchies to only certain types.

This is incredibly useful for pattern matching as you have a specific number of classes to switch between.

The following syntax defines a sealed class in Java 15:

public sealed class Vehicle permits Car, Bike, Truck {...}

In case, you’ve defined the classes CarBike and Truck in the same file as Vehicle, you can omit the keyword permits and the compiler will take care of it implicitly as shown below:

sealed class Vehicle {...} final class Car extends Vehicle {...}final class Bike extends Vehicle {...}final class Truck extends Vehicle {...}

As you can see above, we’ve defined the final modifier of each of the classes. Now, that’s an important rule of sealed class that you need to keep in mind: Every permitted class must be set with an explicit modifier. It can either be final or sealed or non-sealed.

Here’s how each of the modifiers impact inheritance:

  • A permitted subclass that’s declared final cannot be extended further.
  • A permitted subclass that’s declared sealed can be extended further but only by classes that are permitted by the subclass.
  • A permitted subclass may be declared non-sealed can be extended further by any class. The superclass cannot restrict the subclasses further down this class hierarchy.

Before Java 15, developers could only use final keyword or scope modifiers to control inheritance. So, sealed classes brings the added flexibility for Java developers when defining class hierarchies.

2. Records (Second Preview)

Records were introduced as a preview feature in Java 14, in an effort to reduce boilerplate code when writing POJO based data carrier classes. This is something that’s been there in Kotlin for long in the form of data classes.

Now, with Java 15, Records get their second preview. While there aren’t any major changes(just some minor additions), still there are a few major clarifications and restrictions that you should know:

  • Prior to Java 15, one could declare native methods in records(though it wasn’t a good idea). Now the JEP explicitly prohibits against declaring native methods in records. Understandably, defining a native method steals away the USP of records by bringing an external state dependency.
  • The implicitly declared fields corresponding to the record components of a record class are final and should not be modified via reflection now as it will throw IllegalAccessException.

Records are meant to be data carrier classes and you should totally avoid defining native methods in them.

Records with Sealed Types

We know that records are final and cannot be extended. Gladly, records can implement interfaces.

So you can define a sealed interface and implement them on your records in the following ways:

sealed interface Car permits BMW, Audi { ... } record BMW(int price) implements Car { ... } record Audi(int price, String model) implements Car { ... }

Local Records

Records can also be defined within methods to store intermediate values. Unlike local classes, a local record is implicitly static. This means they cannot access variables and instance members of the enclosing methods which is actually great since it prevents capturing of values by the record.

Local records are a great boon for Java developers who would earlier have to create helper records.

See how the introduction of a local records helps perform computation of values in a stream API with the following method:

List<Merchant> findTopMerchants(List<Merchant> merchants, int month) {    // Local record    record MerchantSales(Merchant merchant, double sales) {}     return        .map(merchant -> new MerchantSales(merchant, computeSales(merchant, month)))        .sorted((m1, m2) ->, m1.sales()))        .map(MerchantSales::merchant)        .collect(toList());}

JAVA 16 – Important features –

  • Language enhancements that were introduced in JDK 14 and finalized in JDK 16
  • Improved memory management
  • New Packaging Tool
  • UNIX-Domain Socket Channels
  • Warning for Value-based Classes
  • Encapsulating JDK Internals by default
  • Enable C++ 14 Language Features
  • Incubating and Preview Features

JAVA 17 – Important features –

1: Restore Always-Strict Floating-Point Semantics
2: Enhanced pseudo-Random Number Generators
3: New macOS Rendering pipelines
4: macOS/AArch64 Port
5: Deprecate the Applet API for Removal
6: Strongly Encapsulated JDK Internals
7: Pattern matching for Switch(Preview)
8: Removal RMI Activation
9: Selaled Classes
10: Removal Experimental AOT and JIT Compiler
11: Deprecate the Security manager for Removal
12: Foreign Functions & memory API(Incubator)
13: Vector API(Second Incubator)
14: Context-Specific Deserialization Filters

JAVA 18 – Important features –

Java 18 has below proposed features coming out as part of the JDK 18:
  1. UTF-8 by Default

JAVA 19/20/21 – Important features –

Coming soon…

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.