javagenericsunchecked-exception

Unchecked cast behavior with and without assignment to variable


Why first line in main does not throw ClassCastException while the second does?

import java.util.function.Function;

class Scratch {

    static <T> T getSomething(Function<Integer, T> fun) {
        return (T) fun;
    }

    public static void main(String[] args) {
        Scratch.<String>getSomething(x -> "hello");
        String something = Scratch.<String>getSomething(x -> "hello");
    }
}

Solution

  • The difference is because you don't use the result of the method in the first case, but you do in the second.

    A cast is an expression, but it's not a StatementExpression. This means that you can't write this:

    (String) somethingReturningAString();
    

    but you can write:

    String aString = (String) somethingReturningAString();
    

    At compile time, the compiler inserts checkcast instructions where it needs to, and where it can:


    It's worth noting that there are some perhaps unexpected cases where a cast isn't strictly necessary, but is inserted. For example:

    Scratch.<String>getSomething(x -> "hello").toString();
    

    would fail with a ClassCastException, since it would be transformed to:

    ((String) Scratch.getSomething(x -> "hello")).toString();
    

    even though Object has a toString() method, and so it could invoke that without a cast.