java 8 to 25

  • Java 8 brought functional programming.
  • Java 11 modernized APIs and improved performance.
  • Java 17 gave us elegant syntax with records and pattern matching.
  • Java 25 is shaping up to be all about performance, security, and reducing boilerplate.

Java 8 (Released March 2014) — The Functional Upgrade

Java 8 was a game changer, adding functional programming features.

Key Features

  • Lambda Expressions — cleaner, functional-style code
  • Stream API — process collections like a pro
  • Optional Class — handle null safely
  • New Date/Time API — no more java.util.Date headaches
  • Default Methods in interfaces
  • Metaspace replaces PermGen for better memory management
  • Functional interfaces

Java 17 (Released September 2021) — The Elegant Upgrade

Java 17 added language features that make code concise and expressive.

Key Features

  • Records — easy, immutable data classes
  • Sealed Classes — control inheritance cleanly
  • Pattern Matching for instanceof – less casting noise
  • Foreign Function & Memory API (incubator)
  • Better random number generators
  • Removed Nashorn, Security Manager deprecated

Java 25 (Coming September 2025) — The Future Upgrade

Java 25 is the next LTS release, focusing on performance, memory efficiency, and cleaner syntax.

Key Features

  • Compact Object Headers — ~22% memory savings, faster execution
  • Key Derivation Function (KDF) API — secure, future-proof cryptography
  • Scoped Values — safe alternative to ThreadLocal
  • Module Import Declarations — import entire modules in one line
  • Flexible Constructors — statements allowed before super() or this()
  • Dropped 32-bit x86 support

Java 8 features:

1. Lambda Expressions

Cleaner anonymous function syntax.

List<String> names = Arrays.asList("Ram", "Shyam", "Hari"); names.forEach(name -> System.out.println(name));

2. Stream API

Functional-style processing of collections.

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); int sumOfSquares = nums.stream() .map(n -> n * n) .filter(n -> n > 5) .reduce(0, Integer::sum); System.out.println(sumOfSquares);

3. Optional Class

Handle null safely.

Optional<String> opt = Optional.ofNullable(null); System.out.println(opt.orElse("Default Value"));

4. New Date/Time API (java.time)

Better date handling than java.util.Date.

LocalDate today = LocalDate.now(); LocalDate nextWeek = today.plusWeeks(1); System.out.println("Today: " + today); System.out.println("Next Week: " + nextWeek);

5. Default Methods in Interfaces

Allows methods with implementation inside interface.

interface Vehicle { default void horn() { System.out.println("Beep beep!"); } } class Car implements Vehicle {} new Car().horn();

7. Functional Interfaces

Interface with a single abstract method.

@FunctionalInterface interface MyFunc { void greet(String name); } public class Main { public static void main(String[] args) { MyFunc f = n -> System.out.println("Hello, " + n); f.greet("Subash"); } }


Types of Functional Interfaces

1️⃣ Supplier Takes no input, Returns a value get() method Use case: lazy data generation, random values Supplier<String> supplier = () -> "Hello World"; System.out.println(supplier.get()); 2️⃣ Consumer Takes input, Returns nothing accept() method Use case: printing, logging, updating values
Consumer<String> consumer = name -> System.out.println("Hello " + name); consumer.accept("Ram"); 3️⃣ BiConsumer Takes two inputs, Returns nothing BiConsumer<String, Integer> biConsumer = (name, age) -> System.out.println(name + " is " + age + " years old"); biConsumer.accept("Shyam", 25); 4️⃣ Function Takes input, Returns output apply() method Use case: mapping, converting types Function<String, Integer> function = str -> str.length(); System.out.println(function.apply("Java")); // 4 5️⃣ BiFunction Takes two inputs, Returns output BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b; System.out.println(add.apply(5, 3)); // 8 6️⃣ Predicate Takes input, Returns boolean test() method Use case: filtering, validation Predicate<Integer> isEven = n -> n % 2 == 0; System.out.println(isEven.test(10)); // true 7️⃣ BiPredicate Two inputs, Returns boolean BiPredicate<String, String> startsWith = (s1, s2) -> s1.startsWith(s2); System.out.println(startsWith.test("Ram", "R")); // true 8️⃣ Runnable (core Java functional interface) No input, no output Runnable run = () -> System.out.println("Running thread"); new Thread(run).start();

Java 17 features:

1. Records — immutable data classes (Java 14+)

Before (Old way)

class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }

After (Record)

public record Person(String name, int age) {} public class Test { public static void main(String[] args) { Person p = new Person("Ram", 25); System.out.println(p.name() + " - " + p.age()); } }

✔ Auto-generates constructor, getters, toString(), equals(), hashCode()
✔ Immutable by default


2. Sealed Classes — controlled inheritance (Java 17)

sealed interface Vehicle permits Car, Bike {} final class Car implements Vehicle {} final class Bike implements Vehicle {} // ❌ Bus cannot implement Vehicle unless permitted

✔ You control who can extend or implement
✔ Supports sealed, non-sealed, and final


3. Pattern Matching for instanceof (Java 16)

Before

if (obj instanceof String) { String s = (String) obj; // cast needed System.out.println(s.toUpperCase()); }

After

if (obj instanceof String s) { // smart cast System.out.println(s.toUpperCase()); }

✔ No explicit cast
✔ Cleaner, safer type check


4. Foreign Function & Memory API (Java 19/20+)

Call native code (C/C++), manage off-heap memory without JNI

import java.lang.foreign.MemorySegment; import java.lang.foreign.Arena; public class MemoryExample { public static void main(String[] args) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(100); segment.set(JAVA_INT, 0, 42); System.out.println(segment.get(JAVA_INT, 0)); } } }

✔ Replaces manual JNI
✔ Safe & fast native interaction
Still evolving; became stable in Java 22


5. Better Random Number Generators (Java 17)

import java.util.random.RandomGenerator; import java.util.random.RandomGeneratorFactory; public class RandomExample { public static void main(String[] args) { RandomGenerator rng = RandomGeneratorFactory.of("L64X128MixRandom").create(); System.out.println(rng.nextInt()); } }

✔ Modern RNG algorithms (faster, better quality)
✔ More choices than java.util.Random


6. Removed Nashorn, Security Manager deprecated

❌ Nashorn JavaScript engine removed (Java 15)

// Old (removed) ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval("print('Hello JS from Java')");

Use GraalVM JavaScript instead.


❌ Security Manager deprecated (Java 17)

Security model changed — no new code should rely on it:

// Old System.setSecurityManager(new SecurityManager()); // Deprecated


Java 25 feature:

✅ Compact Object Headers

Goal: Reduce memory footprint of objects (~22% savings) and improve performance. What it does Java internally stores metadata in object headers (class pointer, monitor info, hash, GC age, etc). Compact Object Headers store this metadata more efficiently on modern 64-bit JVMs. Benefits Less memory usage (especially for large object graphs) Better CPU cache locality → faster execution No code required — it’s a JVM optimization enabled by default in recent Java releases (ZGC + Lilliput project).

✅ Key Derivation Function (KDF) API (Java 21)

Goal: Securely derive cryptographic keys from passwords / secrets. Built-in standard API instead of using external libraries. Example (PBKDF2) import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import java.util.HexFormat; public class KDFExample { public static void main(String[] args) throws Exception { char[] password = "MySecurePass".toCharArray(); byte[] salt = "12345678".getBytes(); PBEKeySpec spec = new PBEKeySpec(password, salt, 65536, 256); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] key = factory.generateSecret(spec).getEncoded(); System.out.println(HexFormat.of().formatHex(key)); } } Why useful Protect passwords Safe key derivation (PBKDF2, Argon2, Scrypt supported by JEP)

✅ Scoped Values (Java 21)

Goal: Safer alternative to ThreadLocal for sharing data in threads + structured concurrency. Immutable Works across virtual threads Thread-safe Example import jdk.incubator.concurrent.ScopedValue; public class ScopedExample { static final ScopedValue<String> USER = ScopedValue.newInstance(); public static void main(String[] args) { ScopedValue.runWhere(USER, "Ram", () -> { System.out.println("Hello " + USER.get()); }); } } Why better than ThreadLocal? ThreadLocal Scoped Values Mutable Immutable Error-prone Safe lifecycle Not ideal for virtual threads Designed for virtual threads

✅ Module Import Declarations

Ability to import entire module instead of individual packages – used in Java Platform Module System (JPMS). Example (module-info.java) module my.app { requires java.sql; requires com.example.utils; // importing module } Benefit Modular software design, strong encapsulation, faster startup.

✅ Flexible Constructors (Java 21)

Statements are allowed before super() or this() calls (as long as they don’t use this yet) Before (compile error) class Example { Example() { int id = 10; // ❌ not allowed before super() super(); } } Now allowed class Example { Example() { int id = computeId(); // ✅ allowed now super(); System.out.println("Object created"); } int computeId() { return 100; } } Used for validation, computation, access checks before invoking parent constructor.

❌ Dropped 32-bit x86 Support

Java no longer supports running JVM on 32-bit x86 systems. Why? Most modern machines are 64-bit Performance + security reasons If you try running Java on 32-bit Windows/Linux — JVM won't support it anymore.

Comments

Popular posts from this blog

Archunit test

Hexagonal Architecture

visitor design pattern