A comprehensive guide to all Java 23 concepts with practical examples for interview preparation.
- Primitive Types in Patterns, instanceof, and switch (Preview)
- Module Import Declarations (Preview)
- Stream Gatherers (Second Preview)
- Scoped Values (Third Preview)
- Class-File API (Second Preview)
- Markdown Documentation Comments
- Flexible Constructor Bodies (Second Preview)
- String Templates (Third Preview)
- Implicitly Declared Classes and Instance Main Methods (Third Preview)
- Structured Concurrency (Third Preview)
- Foreign Function & Memory API (Finalized)
- Vector API (Eighth Incubator)
- ZGC: Generational Mode by Default
- Common Interview Questions
Pattern matching with primitive types for more consistent and expressive code.
This feature allows you to use primitive types directly in pattern matching expressions, making pattern matching work consistently for both reference and primitive types.
// Primitive types in patterns (preview)
Object obj = 42;
if (obj instanceof int i) {
System.out.println("Integer: " + i);
}
// In switch
String result = switch (obj) {
case int i when i > 0 -> "Positive: " + i;
case int i -> "Zero or negative: " + i;
case double d -> "Double: " + d;
case boolean b -> "Boolean: " + b;
default -> "Other";
};
// Pattern matching with primitives
Number num = 42;
if (num instanceof Integer i && i > 0) {
System.out.println("Positive integer: " + i);
}- More consistent pattern matching
- Better type safety
- Unified approach for all types
- Eliminates need for wrapper types in patterns
- More expressive code
See PrimitiveTypesInPatterns.java for complete example.
Simplified syntax for importing modules, making module descriptors cleaner and easier to read.
Module Import Declarations allow you to import all packages exported by a module with a single statement, simplifying the reuse of modular libraries.
// Current syntax
module com.example.app {
requires java.base;
requires java.sql;
exports com.example.app.api;
}// Module import declarations (preview)
import module java.base;
import module java.sql;
module com.example.app {
// Modules imported above are available
exports com.example.app.api;
}- Simpler module syntax
- Cleaner module descriptors
- Easier to read
- Reduces boilerplate
- Better module organization
See ModuleImportDeclarations.java for complete example.
Custom intermediate stream operations that extend the Stream API functionality.
Stream Gatherers allow you to create custom intermediate operations for streams, providing more flexibility than existing operations.
import java.util.stream.Gatherer;
import java.util.stream.Gatherers;
// Custom gatherer
Gatherer<String, ?, String> filterAndUpper = Gatherer.ofSequential(
() -> new Object[1],
(state, element, downstream) -> {
if (element.length() > 5) {
return downstream.push(element.toUpperCase());
}
return true;
},
(state, downstream) -> {}
);
// Use gatherer
List<String> result = Stream.of("apple", "banana", "cherry", "kiwi")
.gather(filterAndUpper)
.toList();// Sliding window
List<List<Integer>> windows = Stream.of(1, 2, 3, 4, 5)
.gather(Gatherers.windowSliding(3))
.toList();
// Fixed window
List<List<Integer>> fixed = Stream.of(1, 2, 3, 4, 5, 6)
.gather(Gatherers.windowFixed(3))
.toList();
// Fold operation
String result = Stream.of("a", "b", "c")
.gather(Gatherers.fold(() -> "", (acc, elem) -> acc + elem))
.findFirst()
.orElse("");- Extend Stream API
- Create reusable operations
- More expressive code
- Better performance for custom operations
See StreamGatherersDemo.java for complete example.
Refinements to scoped values with improved performance and safety.
Scoped values provide a way to share immutable data within and across threads, offering a safer alternative to ThreadLocal.
import java.util.concurrent.ScopedValue;
final ScopedValue<String> USER = ScopedValue.newInstance();
ScopedValue.runWhere(USER, "Alice", () -> {
String user = USER.get();
// Use value
});- Immutable values
- Inherited by child threads
- Automatic cleanup
- Better performance than ThreadLocal
- Structured scoping
See ScopedValues.java for complete example.
API for parsing, generating, and transforming Java class files.
The Class-File API provides a standard way to work with Java class files, facilitating tools and frameworks that manipulate bytecode.
- Parse class files
- Generate class files
- Transform bytecode
- Standard API for class file manipulation
- Better than ASM for some use cases
- Bytecode manipulation tools
- Code generation frameworks
- Static analysis tools
- Compiler plugins
- Runtime code generation
- Standard API
- Type-safe operations
- Better than third-party libraries
- Integrated with JDK
Note: This is an advanced API primarily for tool developers and frameworks.
Allows the use of Markdown syntax in Javadoc comments, making documentation more readable and easier to write.
Java 23 allows you to use Markdown syntax directly in Javadoc comments, providing better formatting and readability.
/**
* # Example Method
*
* This method demonstrates **Markdown** syntax in Javadoc.
*
* ## Features
*
* - **Bold text** using `**text**`
* - *Italic text* using `*text*`
* - Code blocks using backticks
*
* ### Usage
*
* ```java
* example.exampleMethod();
* ```
*/
public void exampleMethod() {
// Implementation
}- Headers (#, ##, ###)
- Bold text (text)
- Italic text (text)
- Code blocks (```)
- Inline code (
code) - Lists (-, *, 1.)
- Links (text)
- Tables
- More readable documentation
- Easier to write
- Better formatting
- Standard Markdown syntax
- Works with existing Javadoc tools
See MarkdownDocumentationComments.java for complete example.
Allows statements before super() call in constructors, providing more flexibility in object initialization.
This feature allows you to add logic before calling a superclass constructor, enabling validation and preprocessing.
class Child extends Parent {
Child(String name) {
// Statements before super() (preview)
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Name cannot be null or blank");
}
String processed = name.trim().toUpperCase();
String validated = validate(processed); // Static method call allowed
super(validated); // Now allowed after statements (preview)
}
private static String validate(String s) {
return s.length() > 0 ? s : "Default";
}
}- Statements before super() call
- Validation and preprocessing
- Static method calls allowed
- Instance methods not allowed before super()
- More flexibility in constructors
- Can do validation/preprocessing before super()
- Better code organization
- Allows static method calls before super()
See FlexibleConstructorBodies.java for complete example.
Note: String Templates were withdrawn in Java 23+ due to design concerns. See StringTemplates.java for details.
Refinements to unnamed classes with improved support for simple programs.
This feature simplifies the creation of Java programs by allowing implicit class declarations and instance main methods, reducing boilerplate code.
// Simplified class structure (preview)
void main() {
System.out.println("Hello, World!");
}
// Compiler generates class automatically- Reduced boilerplate
- Easier for beginners
- Good for simple scripts
- More intuitive syntax
See UnnamedClassesAndInstanceMain.java for complete example.
Continued improvements to structured concurrency with enhanced error handling and lifecycle management.
Structured concurrency treats groups of related tasks as a single unit, ensuring proper lifecycle management and error handling.
import java.util.concurrent.StructuredTaskScope;
// Enhanced structured concurrency
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> fetchUser());
Future<String> order = scope.fork(() -> fetchOrder());
scope.join();
scope.throwIfFailed();
// Use results
}- Structured lifecycle management
- Error propagation
- Shutdown strategies
- Automatic resource cleanup
- Prevents thread leaks
See StructuredConcurrency.java for complete example.
The Foreign Function & Memory API is now a standard feature, providing a safer and more efficient alternative to JNI.
This API enables Java programs to interoperate with native code and manage off-heap memory in a type-safe manner, replacing the need for JNI boilerplate.
import java.lang.foreign.*;
// Link with native libraries
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
);
// Allocate and use memory
try (Arena arena = Arena.ofConfined()) {
MemorySegment segment = arena.allocate(100);
// Use memory
}- Type-safe native interop
- Memory safety with arenas
- No JNI boilerplate
- Better performance than JNI
- Structured memory management
- Finalized API (stable)
- Call native code
- Access off-heap memory
- High performance interop
- Safe memory management
- Production-ready (finalized)
See ForeignFunctionMemoryDemo.java for complete example.
Continued improvements to Vector API with enhanced SIMD operations.
The Vector API provides SIMD-style operations for parallel processing of arrays, with hardware-optimized computations that can significantly improve performance.
import jdk.incubator.vector.*;
// SIMD operations
// Enhanced performance for vectorized operations- Hardware-agnostic: Works on different platforms
- Automatic optimization: Compiles to optimal instructions
- Type-safe: Supports int, long, float, double
- SIMD operations: Parallel processing of multiple elements
- Platform-specific optimizations
- Scientific computing
- Machine learning
- Image processing
- Signal processing
- Numerical simulations
- Cryptography
See VectorAPIDemo.java for complete example.
The Z Garbage Collector now operates in generational mode by default, improving application throughput and reducing memory footprint.
Generational ZGC enhances the Z Garbage Collector by introducing generational capabilities, separating young and old objects for more efficient collection.
- Generational collection: Young objects collected more frequently
- Reduced pause times: Better application responsiveness
- Low latency: Maintains ZGC's low-latency characteristics
- Better throughput: Improved overall performance
- Automatic tuning: Self-tuning based on workload
- Default mode: Enabled by default in Java 23
- Objects are divided into young and old generations
- Young generation is collected more frequently
- Old generation is collected less frequently
- Reduces the amount of work per collection cycle
- Lower pause times
- Better throughput
- Improved application responsiveness
- Automatic optimization
- Maintains low latency
- Default behavior (no configuration needed)
# ZGC is default in Java 23+
# No configuration needed
# Disable generational mode (if needed)
-XX:+UseZGC -XX:-ZGenerational
# Tune young generation size
-XX:ZYoungGenerationSizeLimit=2G- Low-latency applications
- Large heap sizes
- Applications requiring predictable pause times
- Real-time systems
- High-throughput applications
Note: Generational ZGC is the default in Java 23. No code changes are required.
A: API for:
- Calling native code from Java
- Accessing off-heap memory
- Safe memory management
- High-performance interop
A: Simplified syntax for modules:
import modulestatements- Cleaner module descriptors
- Easier to read
A: Pattern matching with primitive types:
instanceof int i- Patterns work with primitives
- Consistent pattern matching
- Eliminates need for wrapper types
A: Custom intermediate stream operations:
- Extend Stream API functionality
- Create reusable stream operations
- Built-in gatherers available (windowSliding, windowFixed, fold)
- More flexible than existing operations
A: Immutable thread-local data sharing:
- Immutable values
- Inherited by child threads
- Automatic cleanup
- Better performance than ThreadLocal
- Structured scoping
A: Markdown syntax in Javadoc:
- Headers, bold, italic, code blocks
- Lists and tables
- More readable documentation
- Easier to write and maintain
A: Statements before super() call:
- Allows validation/preprocessing
- Static method calls allowed
- More flexibility in constructors
- Better code organization
A: ZGC with generational collection:
- Default in Java 23
- Separates young and old objects
- Better throughput
- Lower pause times
- Automatic optimization
Last Updated: 2024
Version: 1.0