With Java 17 I want to compare map entries based upon some criteria, where the map entries are Java classes associated with some value, like this:
Comparator<Map.Entry<Class<?>, Integer>> MY_COMPARATOR =
new Comparator<Map.Entry<Class<?>, Integer>>() { … }
Later I have a list of a list of classes and their associated values (whether it's counts, memory size, or whatever). The twist is that my code is so refined (tongue in cheek) that I happen to know that all these classes extend from FooBar:
List<Map.Entry<Class<? extends FooBar>, Integer>> foobarValues = new ArrayList<>();
Now I just want to sort those map entries using MY_COMPARATOR (to find the smallest/largest classes, the classes most encountered, or whatever MY_COMPARATOR uses as its criteria). But this doesn't work:
java.util.Collections.sort(foobarValues, MY_COMPARATOR);
Java (actually Eclipse 2022-09) tells me:
The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (List<Map.Entry<Class<? extends FooBar>,Integer>>, Comparator<Map.Entry<Class<?>,Integer>>)
I've been working with Java generics for a long time, and my best simplified explanation of what's happening is that the ? super T in Collections.sort() "hides" the lower layer of generics, and that ? super Map.Entry<Class<?>> has no relation to ? super Map.Entry<Class<? extends FooBar>>. (But still, really?.) Actually my mind can't quite grasp the full intricacies of the problem.
But let's say I don't care so much about the problem; I just want the code to work with no warnings. You and I know that the comparator can work with any class that is possible to exist, so it will never cause a ClassCastException and it will never cause heap pollution, and it will never even sneak into your house at night and kill your bamboo plant.
How can I tell Java that it's OK for me to use this comparator? This does not work:
Collections.sort(foo, (Comparator<Map.Entry<Class<? extends FooBar>, Integer>>)MY_COMPARATOR);
I would be happy casting the list being sorted, but this doesn't work either:
Collections.sort((List<Map.Entry<Class<?>, Integer>>)foo, MY_COMPARATOR);
This does work!
Collections.sort(foo, (Comparator<Map.Entry<Class<? extends FooBar>, Integer>>)(Object)comparator);
But to use it I have to add @SuppressWarnings("unchecked"), and Java 17 javac with -Xlint:all still complains, and besides I feel dirty using it.
I would be content with some workaround that would allow me to suppress the warning with @SuppressWarnings("unchecked") as long as javac lint still didn't complain. But the intermediate cast to Object is too much of a kludge for me to accept.
What should I be doing?