SonarLint Rule S1612 contradicts S6202 regarding "instanceof" vs. "A.class.isInstance()"

It might be a rather hypothetical example, but consider the following snippet:

    static class A {}
    static class B {}

    public static List<B> convert(List<A> list) {
        return list.stream()
                .filter(a -> a instanceof B)
                .map(a -> (B) a)
                .collect(Collectors.toList());
    }

This will not compile, since the compiler can statically deduce that A can never be an instance of B.

Rule S1612 suggests to convert the lambda expressions into method references:

        return list.stream()
                .filter(B.class::isInstance)
                .map(B.class::cast)

Now it will compile, since Class.cast and Class.isInstance do type checking at runtime. This may lead to runtime failures, e.g. if you leave out the filter in above example, a ClassCastException will be thrown.

I suppose, this is precisely why S6202 suggests that "instanceof" should be used instead of "A.class.isInstance()".


IntelliJ IDEA 2019.3.5 (Community Edition)
SonarLint plugin 6.4.3.42541

3 Likes

Rule S6202 also says that it will work at compile time, not at runtime. That also causes problems with code obfuscation and reflection.

Hi @makohn,
Thanks for the report. We are indeed making a bad suggestion here and S1612 should not raise an issue on your example.

A ticket has been created to fix the issue.

Dorian