Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Key New Features in JDK 14

Tech 2

JDK 14 introduced 16 JDK Enhancement Proposals (JEPs). Below are the most notable and practical new features:

  • 343: Packaging Tool (Incubator)
  • 345: G1 Garbage Collector NUMA Memory Allocation Optimization
  • 349: JFR Event Streaming
  • 352: Non-volatile Byte Buffer Mappings
  • 358: Helpful NullPointerExceptions
  • 359: Records (Preview Feature)
  • 361: Switch Expressions (Standardized)
  • 362: Deprecate Solaris and SPARC Ports
  • 363: Remove Concurrent Mark Sweep (CMS) Garbage Collector
  • 364: ZGC on macOS
  • 365: ZGC on Windows
  • 366: Deprecate ParallelScavenge + SerialOld GC Combination
  • 367: Remove Pack200 Tools and API
  • 368: Text Blocks (Second Preview Feature)
  • 370: External Memory API (Incubator)

Pattern Matching for instanceof

This JEP adds pattern matching capabilities to the instanceof operator, making type checking and conversion more concise, readable, and safer.

Design Goals

When writing code that handles different object types, you typically need to check an object's type then cast it to the target type. The traditional approach has several pain points.

Traditional Type Check and Cast

public void legacyTypeCheck(Object inputObj) {
    if (inputObj instanceof String) {
        String strValue = (String) inputObj;
        System.out.println(strValue.length());
    }
}

This approach requires repeating the type name multiple times, has redundant syntax, and separates the type check and cast steps.

The new pattern matching syntax simplifies this by declaring the target variable directly after the type in the instanceof check:

public void patternMatchingInstanceof(Object inputObj) {
    if (inputObj instanceof String strValue) {
        System.out.println(strValue.length());
    } else {
        // strValue is not accessible here
    }
}

If the check passes, inputObj is automatically cast to String and assigned to strValue, with the variable scoped exclusively to the if block.

Simplified equals() Method

You can also use this feature to simplify the implementation of the equals() method:

import java.util.Objects;

public class Student {
    private final String studentName;

    public Student(String name) {
        this.studentName = name;
    }

    @Override
    public boolean equals(Object obj) {
        return (obj instanceof Student otherStudent) && Objects.equals(this.studentName, otherStudent.studentName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(studentName);
    }
}

Switch Expressions (JEP 361)

This feature standardizes the enhanced switch syntax first introduced in JDK 12 and refined in JDK 14, allowing switch to be used both as a statement and an expression.

Evolution of Java Switch

  • Java 5: Added support for enums
  • Java 7: Added support for String literals
  • Java 11: Added buillt-in fallthrough warnings for missing break statements
  • JDK 12+: Major syntax enhancements to support arrow notation and expression usage

Traditional Switch Syntax

Before JDK 12, switch required expilcit break statements to prevent fallthrough:

public class LegacySwitchDemo {
    public static void main(String[] args) {
        char grade = 'C';
        switch (grade) {
            case 'A':
                System.out.println("Excellent");
                break;
            case 'B':
                System.out.println("Good");
                break;
            case 'C':
                System.out.println("Fair");
                break;
            case 'D':
                System.out.println("Pass");
                break;
            case 'E':
                System.out.println("Fail");
                break;
            default:
                System.out.println("Invalid grade");
        }
    }
}

Arrow Notation Without break

JDK 12 replaced the colon syntax with arrow notation, eliminating the need for break statements:

public class ArrowSwitchDemo {
    public static void main(String[] args) {
        char grade = 'C';
        switch (grade) {
            case 'A' -> System.out.println("Excellent");
            case 'B' -> System.out.println("Good");
            case 'C' -> System.out.println("Fair");
            case 'D' -> System.out.println("Pass");
            case 'E' -> System.out.println("Fail");
            default -> System.out.println("Invalid grade");
        }
    }
}

Note that new and old switch syntax cannot be mixed in the same switch block.

Switch as an Expression

Switch can now be used as an expression that returns a value, assigned directly to a variable:

public class SwitchExpressionDemo {
    public static void main(String[] args) {
        char grade = 'C';
        String gradeLabel = switch (grade) {
            case 'A' -> "Excellent";
            case 'B' -> "Good";
            case 'C' -> "Fair";
            case 'D' -> "Pass";
            case 'E' -> "Fail";
            default -> "Invalid grade";
        };
        System.out.println(gradeLabel);
    }
}

Multi-Case Matching

You can group multiple cases together using comma separation for shared logic:

public class MultiCaseSwitchDemo {
    public static void main(String[] args) {
        char grade = 'B';
        String performance = switch (grade) {
            case 'A', 'B' -> "Top tier";
            case 'C' -> "Middle tier";
            case 'D', 'E' -> "Bottom tier";
            default -> "Invalid grade";
        };
        System.out.println(performance);
    }
}

Yielding Values from Switch Blocks

If your switch case uses a code block instead of a single expression, use the yield keyword to return a value:

public void getGradeResult(int rawScore) {
    char grade = rawScore > 90 ? 'A' : rawScore > 80 ? 'B' : rawScore >70 ? 'C' : rawScore >60 ? 'D' : 'E';
    String result = switch (grade) {
        case 'A', 'B' -> "Top tier";
        case 'C' -> "Middle tier";
        case 'D', 'E' -> "Bottom tier";
        default -> {
            if (rawScore < 0 || rawScore > 100) {
                yield "Score out of valid range (0-100)";
            }
            yield "Unknown grade";
        }
    };
    System.out.println(result);
}

Switch expressions must cover all possible input cases, or include a default block. For enum types, the compiler will automatically add a default block if all enum values are covered.

Text Blocks (JEP 368)

This is the second preview of text blocks, first introduced in JDK 13, designed to simplify writing multi-line string literals by improving readability and reducing boilerplate.

Core Syntax

Text blocks use three double quotes (""") as delimiters. The opening delimiter must be followed by a line break, and the closing delimiter defines the end of the string.

String multiLineText = """
Line 1
Line 2
Line 3
""";

This is equivalent to the traditional concatenated string:

"Line 1\nLine 2\nLine 3\n"

Automatic Indentation Handling

The compiler automatically trims consistent leading whitespace from all lines in the text block, based on the position of the closing delimiter. For example:

String xmlConfig = """
    <root>
        <user>
            <name>Alice</name>
            <id>1001</id>
        </user>
    </root>
    """;

The leading 4 spaces of each line will be removed, prdoucing a properly indented XML string without manual whitespace management. If the closing delimiter is placed at the end of the last content line, no leading whitespace is trimmed:

String compactXml = """
    <root><user><name>Alice</name></user></root>
""";

Special Escape Sequences

Text blocks support two additional escape sequences beyond standard string literals:

  • \: Prevents the insertion of a line break at the current position
  • \s: Represents a single space, to avoid trailing whitespace being automatically trimmed
// Single line string with no line breaks
String singleLineText = """
    Hello \
    World \
    Java 14
    """;

// Fixed-width lines with trailing spaces preserved
String fixedWidthNames = """
    Alice    \s
    Bob      \s
    Charlie  \s
    """;

Common Use Cases

Text blocks excel at writing multi-line content like HTML, SQL queries, and script code:

// Traditional HTML string
String traditionalHtml = "<html>\n" +
    "  <body>\n" +
    "    <p>Hello, World</p>\n" +
    "  </body>\n" +
    "</html>";

// Text block HTML
String modernHtml = """
    <html>
        <body>
            <p>Hello, World</p>
        </body>
    </html>
    """;
// Traditional SQL query
String traditionalSql = "SELECT emp_id, last_name FROM employee_tb\n" +
    "WHERE city = 'INDIANAPOLIS'\n" +
    "ORDER BY emp_id, last_name;";

// Text block SQL
String modernSql = """
    SELECT emp_id, last_name FROM employee_tb
    WHERE city = 'INDIANAPOLIS'
    ORDER BY emp_id, last_name;
    """;
// Traditional JavaScript script
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("js");
Object scriptResult = jsEngine.eval("function hello() {\n" +
    "  print('\"Hello, World\"');\n" +
    "}\n" +
    "\n" +
    "hello();");

// Text block JavaScript script
ScriptEngine modernJsEngine = new ScriptEngineManager().getEngineByName("js");
Object modernScriptResult = modernJsEngine.eval("""
    function hello() {
        print('"Hello, World"');
    }
    
    hello();
    """);
Tags: JavaJDK 14

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.