Please forgive the bad naming, the problem described below is a very crude simplification and alteration of real code
I have the following types defined:
interface Bundle {
// omitted
}
interface Content<T extends Bundle> {
void useBundle(T bundle);
Class<? extends T> getSupportedBundleClass();
// omitted
}
class Service<T extends Bundle> {
private final T bundle;
public Collection<Content<? super T>> someMethod(Collection<Object> allContents) {
// omitted
}
}
The purpose of someMethod in Service is to filter such instances of Content whose supported bundle class is either the same as the bundle's class or higher up the hierarchy.
For example:
Given the hierarchy of Bundle...
interface Bundle {}
interface A extends Bundle {}
class B implements A {}
... and this set-up, ...
Content<Bundle> contentBundle = // omitted
Content<A> contentA = // omitted
Content<B> contentB = // omitted
Service<Bundle> serviceBundle = // omitted
Service<A> serviceA = // omitted
Service<B> serviceB = // omitted
List<Object> allContents = List.of(contentBundle, contentA, contentB);
... the following is true:
serviceBundle.someMethod(allContents) => [contentBundle]
serviceA.someMethod(allContents) => [contentBundle, contentA]
serviceB.someMethod(allContents) => [contentBundle, contentA, contentB]
Here is how someMethod is implemented (with the helper method to do the casting and resolve the wildcard):
public Collection<Content<? super T>> someMethod(Collection<Object> allContents) {
return allContents.stream()
.map(obj -> obj instanceof Content ? (Content<? extends Bundle>) obj : null) // cast #1
.filter(Objects:nonNull)
.map(this::castOrNull)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private <U extends Bundle> Content<? super T> castOrNull(Content<U> content) {
return content.getSupportedBundleClass().isInstance(bundle) ? (Content<? super T>) content : null; // cast #2
}
My reasoning in the castOrNull method is that if the bundle in the Service class is an instance of the supported bundle class of the provided Content instance, then the provided Content's type parameter is a supertype ofT (bundle's type).
someMethod works correctly, as expected (described in the example above). However, I get the unchecked cast warning Content<U> to Content<? super T> on the line with the comment **// cast #2** (the line with **// cast #1** is fine). Is there any way to eliminate the warning (apart from, of course, suppressing it)?