-
Notifications
You must be signed in to change notification settings - Fork 0
Java 10
Release Date: March 20, 2018 | Type: Standard (non-LTS) | Status:
⚠️ End of Life
Java 10 is a smaller release, but it introduced the single most visible day-to-day change since lambdas: the var keyword. It also began Java's move to a 6-month release cadence, which is why versions from here on ship faster with smaller, focused feature sets.
flowchart LR
A["Explicit Types\nMap<String, List<Order>> orders = new HashMap<>();"] --> B["var\nvar orders = new HashMap<String, List<Order>>();"]
B --> C["Compiler infers\nfull type at compile time"]
What: The compiler infers the type of a local variable from its initializer. var is not a dynamic type (unlike JavaScript's var) — the type is fixed at compile time, just not written out.
// Before Java 10
Map<String, List<Order>> ordersByCustomer = new HashMap<>();
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
StringBuilder sb = new StringBuilder();
// With var
var ordersByCustomer = new HashMap<String, List<Order>>();
var names = Arrays.asList("Alice", "Bob", "Charlie");
var sb = new StringBuilder();
// Still fully statically typed!
var sb2 = new StringBuilder();
sb2.append(42); // ✅ fine
// sb2 = 42; // ❌ compile error — sb2 is a StringBuilder, alwaysWhere var can and can't be used:
// ✅ Local variables with initializers
var count = 10;
// ✅ Enhanced for-loop
for (var order : orders) { ... }
// ✅ Traditional for-loop
for (var i = 0; i < 10; i++) { ... }
// ✅ try-with-resources
try (var conn = dataSource.getConnection()) { ... }
// ❌ Fields
// private var name; // NOT allowed
// ❌ Method parameters (until Java 11 added it for lambdas)
// void process(var input) { } // NOT allowed
// ❌ No initializer — type can't be inferred
// var x; // compile error
// ❌ Initializing with null
// var y = null; // compile error — no type to infer// Java 8 required a supplier for a custom exception,
// or get() which threw NoSuchElementException with a poor message
Optional<User> user = findUser(id);
// Java 10: no-arg overload throws NoSuchElementException clearly
User u = user.orElseThrow();List<String> immutableList = names.stream()
.filter(n -> n.length() > 3)
.collect(Collectors.toUnmodifiableList());
Set<String> immutableSet = names.stream()
.collect(Collectors.toUnmodifiableSet());
Map<String, Integer> immutableMap = names.stream()
.collect(Collectors.toUnmodifiableMap(n -> n, String::length));What: Extends class-data sharing (previously JDK classes only) to application classes, reducing JVM startup time and memory footprint by sharing class metadata across JVM instances.
# Generate a class list
java -Xshare:off -XX:DumpLoadedClassList=app.classlist -jar app.jar
# Create the shared archive
java -Xshare:dump -XX:SharedClassListFile=app.classlist \
-XX:SharedArchiveFile=app-cds.jsa -cp app.jar
# Run using the archive (faster startup)
java -Xshare:on -XX:SharedArchiveFile=app-cds.jsa -cp app.jar MainWhy it matters: Meaningful for microservices/serverless where JVM startup time directly affects cold-start latency.
From Java 10 onward, version numbers follow $FEATURE.$INTERIM.$UPDATE.$PATCH and ship every 6 months (March/September), regardless of feature readiness — unfinished features simply stay in "preview" until ready. This is why you'll see the same feature listed across several consecutive versions as it matures.
timeline
title Java Release Cadence (post-Java 9)
2018-03 : Java 10
2018-09 : Java 11 (LTS)
2019-03 : Java 12
2019-09 : Java 13
2020-03 : Java 14
2020-09 : Java 15
2021-03 : Java 16
2021-09 : Java 17 (LTS)
✅ Use var when the right-hand side already makes the type obvious (var list = new ArrayList<String>())
✅ Use var heavily in loop variables and try-with-resources — low risk, high readability win
❌ Avoid var when the initializer doesn't make the type clear (var result = process(x) — what's result?)
❌ Don't use var for public API signatures, fields, or return types — those still need explicit types, and var isn't allowed there anyway
// ❌ Reduces readability — reader must dig into process() to know the type
var result = process(data);
// ✅ Type is obvious from the right-hand side
var users = new ArrayList<User>();
var isValid = validate(input); // boolean is obvious enough from context