Java 26 — All New Features, Removals & Previews
📢 Get actionable Java/Spring Boot insights every week — from practical code tips to real-world use-case based interview questions.
Join 5000+ subscribers and level up your Spring & backend skills with hand-crafted content — no fluff.
First 100 paid subscribers will get the annual membership at $50/year ( 60 already converted to paid, 40 remaining )
Still not convinced? Check out the details of the past work
Java 26 adds a new version enum:
HttpClient.Version.HTTP_3This allows
HttpClientto negotiate and use HTTP/3. HTTP/3 is not an evolution of HTTP/2 over TCP.It uses a completely new transport.HTTP/3 uses QUIC over UDP → not upgradable from HTTP/1.1 or HTTP/2.
Connection-level version negotiation is non-trivial.
API surface change is tiny; complexity is under the hood.
HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_3) .build();
When to use
Latency-sensitive apps.
Packet-loss-heavy networks (QUIC handles loss better).
Services that already support HTTP/3 (e.g., Cloudflare, Google).
Prepare to Make Final Mean Final
Its main goal is to restore the “immutability guarantee” of
finalfields by default. In other words, make it so that once afinalfield is assigned (in a constructor or static initializer), it can’t be overwritten via reflection and related mechanisms.In Java, since JDK 5, “deep reflection” — using
java.lang.reflect.Field.setAccessible(true)+Field::set(...)— has allowed code to override thefinalguarantee: even afinalfield can be changed at runtime.That undermines the semantic meaning of
final: for correctness, reasoning about immutability, thread-safety, etc. Also undermines certain optimizations (like constant-folding) the JVM might perform under the assumption thatfinalfields don’t change.JEP 500 considers the fact that allowing such unconstrained mutation was a “poor choice” and wants to align with the stricter immutability model already used for newer constructs (e.g.
records, hidden classes, etc.)From JDK 26, by default, if code uses reflection (or other deep reflection APIs) to mutate a
finalfield, the JVM will now emit a warning at runtime (instead of silently allowing it).The warning is intended to notify developers of code paths that mutate final fields, to give time to migrate.
In future JDK versions, the plan is for such mutation to be disallowed by default — i.e.
Field::set(...)on a final field will throw an exception rather than succeed (unless explicitly allowed)
JEP 504 proposes to remove the entire java.applet API from the standard Java SE platform.
It was marked Completed and targeted for JDK 26.
The Applet API was deprecated for removal back in JDK 17 (2021).
Web browsers no longer support Java applets — the plugin model that allowed applets to run in browsers is largely dead.
Lazy Constants (Second Preview)
JEP 526 introduces a new API: java.lang.LazyConstant<T> — a holder for a value that is computed lazily (on first demand) but then becomes immutable (“constant”) thereafter.
Lazy constants are treated by the JVM as “true constants,” enabling many of the same performance and optimization benefits that
finalfields enjoy (constant-folding, inlining, etc.) once initialized.Compared to a plain
finalfield, lazy constants give flexibility in when initialization happens — instead of requiring initialization at construction or class-load time.Using
finalfields give immutability — butfinalforces eager initialization (at object creation or class initialization).
In many real-world cases (e.g., heavy resources: loggers, configs, caches, service clients,) you may want to delay initialization until first use to save startup costs.private static final LazyConstant<Logger> LOG = LazyConstant.of(() -> Logger.create(MyService.class));JEP 526 is a refinement / second preview of what had been previously proposed under JEP 502 (“Stable Values”). Changes include:
Renamed the API from
StableValue→LazyConstant— a name better aligned with the high-level use case.Removed lower-level methods (
orElseSet,setOrThrow,trySet) from the API — simplifying it to just “factory + get” style.
Primitive Types in Patterns, instanceof, and switch (Fourth Preview)
JEP 530 makes primitive types (int, long, float, double, boolean, etc.) first‑class participants in Java’s pattern matching,
instanceof, andswitchIt’s a preview language feature in JDK 26.
Historically, pattern matching,
instanceof, andswitchsupported only reference types (objects), or a limited subset of primitive-like types; this JEP removes that restriction.Primitive Type Patterns in
instanceof,switch, Pattern MatchingYou can now write:
if (x instanceof int i) { // i is bound as int } switch (someLongValue) { case 1L -> ... case long l -> ... }instanceofSupports Primitive TypesInstead of only
instanceof SomeClass, you can test primitive‑to‑primitive safe conversions:int i = ...; if (i instanceof byte b) { // tests if i can be losslessly cast to byte // b is byte }switchWorks on All Primitive Types




