What are the Key Features of Java 17 (LTS)?
Java 17 (released September 2021) is a Long-Term Support (LTS) version with 14 JEPs (JDK Enhancement Proposals). It includes sealed classes, pattern matching for switch (preview), records, text blocks, and many enhancements.
1. Sealed Classes (JEP 409) - Final in Java 17
// Sealed class: Specifies permitted subclasses
public sealed class Shape
permits Circle, Rectangle, Triangle {
abstract double area();
abstract double perimeter();
}
final class Circle extends Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
@Override
double perimeter() {
return 2 * Math.PI * radius;
}
}
non-sealed class Rectangle extends Shape {
double length, width;
Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
double area() {
return length * width;
}
@Override
double perimeter() {
return 2 * (length + width);
}
}
final class Triangle extends Shape {
double side1, side2, side3;
Triangle(double s1, double s2, double s3) {
this.side1 = s1;
this.side2 = s2;
this.side3 = s3;
}
@Override
double area() {
double s = (side1 + side2 + side3) / 2;
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
@Override
double perimeter() {
return side1 + side2 + side3;
}
}
// Cannot extend Shape from other packages/files
// class AnotherShape extends Shape { } // COMPILE ERROR
public class SealedClassesDemo {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
Shape triangle = new Triangle(3, 4, 5);
System.out.println("Circle area: " + circle.area());
System.out.println("Rectangle area: " + rectangle.area());
System.out.println("Triangle area: " + triangle.area());
// Sealed classes provide exhaustive checking
double totalArea = 0;
for (Shape shape : Arrays.asList(circle, rectangle, triangle)) {
totalArea += shape.area();
}
System.out.println("Total area: " + totalArea);
}
}
2. Records (Standard since Java 16, Final in Java 17)
// Before Java 16 - verbose POJO
class PointOld {
private int x;
private int y;
PointOld(int x, int y) {
this.x = x;
this.y = y;
}
int getX() { return x; }
int getY() { return y; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PointOld point = (PointOld) o;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
@Override
public String toString() {
return "PointOld[x=" + x + ",y=" + y + "]";
}
}
// Java 17 Record (immutable data carrier)
record Point(int x, int y) {}
// Record with validation and custom methods
record Person(String name, int age) {
// Compact constructor for validation
public Person {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Name is required");
}
// Normalization
name = name.trim();
}
// Additional constructor
public Person(String name) {
this(name, 18); // Default age 18
}
// Custom methods
public String greeting() {
return "Hello, I'm " + name;
}
public boolean isAdult() {
return age >= 18;
}
}
// Record with generics
record Pair(K key, V value) {
@Override
public String toString() {
return key + "=" + value;
}
}
// Record implementing interface
interface WithName {
String name();
}
record Employee(String name, int id, String department) implements WithName {}
public class RecordsDemo {
public static void main(String[] args) {
Point p1 = new Point(10, 20);
Point p2 = new Point(10, 20);
System.out.println(p1); // Point[x=10, y=20]
System.out.println("x: " + p1.x()); // Accessor methods
System.out.println("Equals: " + p1.equals(p2)); // true
System.out.println("HashCode: " + p1.hashCode());
Person person = new Person("Alice", 25);
System.out.println(person.greeting());
System.out.println("Is adult? " + person.isAdult());
Pair pair = new Pair<>("Age", 30);
System.out.println(pair);
Employee emp = new Employee("Bob", 101, "IT");
System.out.println(emp.name()); // Implementing interface
}
}
3. Text Blocks (Standard since Java 15, Final in Java 17)
public class TextBlocksDemo {
public static void main(String[] args) {
// Before Java 15
String htmlOld = "
" +
"
" +
" Hello
" +
"
" +
"";
// Java 17 Text Block
String html = """
Hello, World!
This is a text block in Java 17
- Item 1
- Item 2
""";
System.out.println(html);
// SQL Query example
String sql = """
SELECT id, name, email, created_at
FROM users
WHERE status = 'ACTIVE'
AND age >= 18
ORDER BY created_at DESC
LIMIT 10
""";
System.out.println(sql);
// JSON example
String json = """
{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"address": {
"street": "123 Main St",
"city": "New York",
"zip": "10001"
}
}
""";
System.out.println(json);
// Escape sequences
String escaped = """
Line 1: Hello
Line 2: Quote in text: "quoted"
Line 3: Backslash: \\
Line 4: Newline in text:
This is on next line
""";
System.out.println(escaped);
// Trailing spaces (use s)
String spaces = """
Line with trailing spaces:sss
Next line
""";
// XML example
String xml = """
Java 17 Fundamentals
Online Learner
2024
""";
System.out.println(xml);
}
}
4. Pattern Matching for switch (Preview - JEP 406/420/427)
// Note: Pattern matching for switch is preview in Java 17
// Run with: javac --enable-preview --release 17
public class PatternMatchingSwitch {
record Point(int x, int y) {}
record Circle(double radius) {}
record Rectangle(double length, double width) {}
sealed interface Vehicle permits Car, Bike, Truck {}
record Car(String brand, int year) implements Vehicle {}
record Bike(String type) implements Vehicle {}
record Truck(double capacity) implements Vehicle {}
static String processShape(Object obj) {
return switch(obj) {
case null -> "Null object";
case Circle c -> "Circle with radius: " + c.radius();
case Rectangle r -> "Rectangle: " + r.length() + "x" + r.width();
case Point(var x, var y) -> "Point at (" + x + "," + y + ")";
case String s when s.length() > 5 -> "Long string: " + s;
case String s -> "Short string: " + s;
case Integer i when i > 0 -> "Positive integer: " + i;
case Integer i -> "Non-positive integer: " + i;
case int[] arr -> "Array of length: " + arr.length;
default -> "Unknown type";
};
}
static String processVehicle(Vehicle v) {
return switch(v) {
case Car(String brand, int year) ->
"Car: " + brand + " (" + year + ")";
case Bike(String type) when type.equals("mountain") ->
"Mountain Bike";
case Bike(String type) -> "Bike: " + type;
case Truck(double capacity) when capacity > 10 ->
"Large Truck (capacity: " + capacity + " tons)";
case Truck(double capacity) -> "Truck (capacity: " + capacity + " tons)";
};
}
public static void main(String[] args) {
System.out.println("=== Pattern Matching Demo ===");
System.out.println(processShape(new Circle(5)));
System.out.println(processShape(new Rectangle(4, 6)));
System.out.println(processShape(new Point(10, 20)));
System.out.println(processShape("Hello"));
System.out.println(processShape("Long String Here"));
System.out.println(processShape(42));
System.out.println(processShape(-5));
System.out.println(processShape(null));
System.out.println("
=== Vehicle Processing ===");
System.out.println(processVehicle(new Car("Toyota", 2022)));
System.out.println(processVehicle(new Bike("mountain")));
System.out.println(processVehicle(new Bike("road")));
System.out.println(processVehicle(new Truck(15.5)));
System.out.println(processVehicle(new Truck(5.0)));
}
}
5. Enhanced Pseudo-Random Number Generators (JEP 356)
import java.util.random.*;
public class RandomGeneratorDemo {
public static void main(String[] args) {
System.out.println("=== Enhanced Random Generators ===
");
// Legacy Random (still works)
Random legacyRandom = new Random();
System.out.println("Legacy Random: " + legacyRandom.nextInt(100));
// New RandomGenerator interface
RandomGenerator generator = RandomGenerator.of("L64X128MixRandom");
System.out.println("
Available Random Generators:");
System.out.println("- L64X128MixRandom (fast, good quality)");
System.out.println("- L64X256MixRandom");
System.out.println("- L128X128MixRandom");
System.out.println("- L128X256MixRandom");
System.out.println("- Xoroshiro128PlusPlus");
System.out.println("- Xoshiro256PlusPlus");
// Generating random values
System.out.println("
Random values:");
System.out.println(" int: " + generator.nextInt());
System.out.println(" int bound: " + generator.nextInt(100));
System.out.println(" long: " + generator.nextLong());
System.out.println(" double: " + generator.nextDouble());
System.out.println(" boolean: " + generator.nextBoolean());
// Streams of random numbers
System.out.println("
Random ints stream (5 numbers):");
generator.ints(5).forEach(n -> System.out.print(n + " "));
System.out.println("
Random doubles (5 numbers):");
generator.doubles(5, 0.0, 1.0).forEach(d -> System.out.printf("%.3f ", d));
// Thread-safe generators
System.out.println("
Thread-safe generator:");
RandomGenerator threadSafe = RandomGeneratorFactory.of("L64X128MixRandom")
.create(System.nanoTime());
System.out.println(" " + threadSafe.nextInt(100));
}
}
6. Other Java 17 Features
public class OtherJava17Features {
public static void main(String[] args) {
System.out.println("=== Other Java 17 Features ===
");
// 1. Switch Expressions (Standard)
System.out.println("1. Switch Expressions:");
String day = "MONDAY";
String type = switch(day) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
case "SATURDAY", "SUNDAY" -> "Weekend";
default -> "Invalid";
};
System.out.println(" " + day + " is " + type);
// 2. Helpful NullPointerExceptions
System.out.println("
2. Helpful NullPointerExceptions:");
System.out.println(" -JVM option: -XX:+ShowCodeDetailsInExceptionMessages");
System.out.println(" -Provides detailed NPE messages");
// 3. Deprecating Applet API for Removal
System.out.println("
3. Applet API deprecated for removal");
// 4. Strongly Encapsulate JDK Internals
System.out.println("
4. Strong Encapsulation of JDK Internals");
System.out.println(" - Illegal reflective access now disabled by default");
System.out.println(" - Use --add-opens to open modules");
// 5. Foreign Function & Memory API (Incubator)
System.out.println("
5. Foreign Function & Memory API (Incubator)");
System.out.println(" - Direct access to native code and memory");
// 6. Vector API (Second Incubator)
System.out.println("
6. Vector API (Second Incubator)");
System.out.println(" - Vector computations for performance");
// 7. MacOS rendering pipeline
System.out.println("
7. New macOS Rendering Pipeline");
System.out.println(" - Better performance on macOS");
// 8. Unix-domain socket channels
System.out.println("
8. Unix-domain Socket Channels");
System.out.println(" - Local IPC support");
}
}
Java Version Timeline
| Version | Release Date | LTS | Key Features |
|---|---|---|---|
| Java 8 | March 2014 | Yes | Lambdas, Stream API, Optional |
| Java 9 | September 2017 | No | Modules (Jigsaw), JShell |
| Java 11 | September 2018 | Yes | HTTP Client, Local var for lambda |
| Java 17 | September 2021 | Yes | Sealed classes, Records, Text blocks |
| Java 21 | September 2023 | Yes | Virtual threads, Pattern matching |
Master Java 17 LTS features with Online Learner!
0
likes
Your Feedback
Help us improve by sharing your thoughts
Online Learner helps developers master programming, database concepts, interview preparation, and real-world implementation through structured learning paths.
Quick Links
© 2023 - 2026 OnlineLearner.in | All Rights Reserved.
