I know that Java generic type information is erased at runtime. I have sort-of-abused this to put "wrongly typed" objects into maps to mark mapping to nulls:
import java.util.*;
public class test
{
private static final Object NULL = new Object();
public static void main(String[] args) throws Exception
{
Map<String, String> kek = new HashMap<>();
kek.put("foo", maskNull(null));
}
@SuppressWarnings ("unchecked")
public static <T> T maskNull(T value)
{
return value != null ? value : (T) NULL;
}
}
Of course in real code I would use sth. like maskNull(foo) where foo could be anything, so I wouldn't know if it was null or not in advance. Functions like isMaskedNull() etc. are omitted for brevity.
This used to work fine in Java 8. However, now that I'm trying to upgrade to Java 11, I get the following error at runtime:
Exception in thread "main" java.lang.ClassCastException: class java.lang.Object cannot be cast to class java.lang.String (java.lang.Object and java.lang.String are in module java.base of loader 'bootstrap')
at test.main(test.java:10)
As I understand, Java compiler now implicitly emits type-casting operation before put() is called. Is there a way out of it, i.e. can I get the old behavior at least in specifically marked (I don't know, with an annotation?) cases?