Serguey Asael Shinder: List.of(...).contains(null) throws, and the javadoc allows it
A check like this looks harmless:
List<String> allowed = List.of("read", "write");
if (allowed.contains(role)) { ... }
If role is null, it does not return false. It throws NullPointerException.

That surprises people because a HashSet or an ArrayList would simply answer false. But the contract was never "contains answers false for null". The javadoc of Collection.contains) lists, under its exceptions: NullPointerException — if the specified element is null and this collection does not permit null elements (optional). Optional means an implementation may throw or may not.
The collections from the static factories are the ones that do not permit nulls. The List javadoc, section "Unmodifiable Lists" says the lists created by List.of and List.copyOf "disallow null elements". And the JDK's implementation chooses the throwing option: in ImmutableCollections.java the small two-element list starts indexOf with Objects.requireNonNull(o), the general list throws NullPointerException when nulls are not allowed and the argument is null, and contains is implemented through indexOf. The set built by Set.of calls Objects.requireNonNull(o) in contains directly, and the single-entry Map.of relies on o.equals(k0) in containsKey — the source comment calls it an "implicit nullcheck".
What to do about it:
- Decide what a null input means before the lookup, not inside it. If an absent role should be denied, write that:
role != null && allowed.contains(role). - Do not rely on the exception as validation. It is optional in the contract, so another implementation of the same interface may return
falseinstead. - Treat
containsKeyonMap.ofmaps the same way — as the source above shows, the single-entry map null-checks its argument there too.
The rule underneath is old: an interface method whose javadoc says "optional" next to an exception is telling you that two correct implementations may behave differently on that input. The factory collections are simply the ones most people meet first.