Java unchecked cast to type parameter warning despite being instance of

348 Views Asked by At

Consider you have this List:

private final List<? extends AbstractXmlElement> inMemoryElements;

that contains a bunch of objects of subclasses of AbstractXmlElement and you want to add a method to filter objects of a specific subclass from that list. For this I created the following method:

public <E extends AbstractXmlElement> List<E> getInstancesOf(Class<E> c) {
    return getUsableElements().stream()
        .filter(c::isInstance)
        .map(e -> (E) e)
        .collect(Collectors.toList());
}

Yet (E) e results in an UncheckedCast Warning. I was wondering how exactly this is an unchecked cast and if it is safe to suppress this warning since those objects that are not an instance of E are filtered out before the cast. Meaning that, as far as I know, the cast should never fail

2

There are 2 best solutions below

0
On BEST ANSWER

It's an unchecked cast because the type of E is unknown at runtime. Since you're checking isInstance(), your code is safe. But if you want to avoid the warning, you can use c to do the cast:

.map(c::cast)
1
On

how exactly this is an unchecked cast

Your only guarantee is that e is an instance of AbstractXmlElement. But it could be any subclass. So if you had a subclass A and B both extending AbstractXmlElement, theoretically the type constraint means you could attempt to cast A to B, which would fail, if you passed B.class as the argument and your collection contained instances of A. Hence the warning.

Note that the compiler doesn't go and check your filter expression to figure out that only instances of E can ever make it past the filter; in particular it does not go and read documentation and then also assume that documentation is correct. As far as it can tell, c::isInstance() is just another random method taking an Object and returning a boolean. There is at that point nothing to indicate only instances of E remain in the stream past the filter.

if it is safe to suppress this warning

In this case, yes.