With Java 9, new factory methods have been introduced for the List, Set and Map interfaces. These methods allow quickly instantiating a Map object with values in one line. Now, if we consider:
Map<Integer, String> map1 = new HashMap<Integer, String>(Map.of(1, "value1", 2, "value2", 3, "value3"));
map1.put(4, null);
The above is allowed without any exception while if we do:
Map<Integer, String> map2 = Map.of(1, "value1", 2, "value2", 3, "value3", 4, null );
It throws:
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:221)
..
I am not able to get, why null is not allowed in second case.
I know HashMap can take null as a key as well as a value but why was that restricted in the case of Map.of?
The same thing happens in the case of java.util.Set.of("v1", "v2", null) and java.util.List.of("v1", "v2", null).
Map.copyOf(), it throws NPE if the Map contains null value. This is a violation of Map contract. As Map.copyOf() is supposed to be a generic method to accept any kinds of Maps. This breaks existing code at runtime. It's hard to detect with test and compiler check. Maybe a more graceful way is to drop those null values instead of blaster with exceptions. Now we have to write ugly code to get around this check. This makes it very less useful.