The full picture
var names = new ArrayList<String>(); // ✅ ArrayList<String>
var oops = new ArrayList<>(); // ⚠️ ArrayList<Object> — diamond + var
var entry = Map.entry("a", 1); // Map.Entry<String,Integer> — nice
var list = List.of(1, 2.0); // List<? extends Number&Comparable…> 😱
// Target typing: the SAME expression, two types
Comparator<String> byLen = Comparator.comparing(String::length);
Function<String,Integer> f = String::length; // context decides
// Conditional operator surprise:
Object o = flag ? 1 : "x"; // infers Object&Serializable&Comparable… fine
long ms = flag ? 1 : longValue; // numeric promotion — subtle bugs- Team rule of thumb for
var: allowed when the type is obvious from the right side (constructors, factories, casts); avoided for method-call chains returning non-obvious types and in public-facing signatures (where it's illegal anyway). - Generic method inference failure mode: when inference picks a common supertype you didn't want, add an explicit witness —
Collections.<Runnable>emptyList(). varin lambda parameters (Java 11) exists mainly to hang annotations on:(@Nonnull var x) -> ….