Hc Frank
Hc Frank

Reputation: 1

How compiler to assure type safety in java?

We know generic type safety in java is a compile time check. But these two pieces of code confuse me:

private static final UnaryOperator<Object> IDENTITY_FN = (t) -> t;

@SuppressWarnings("unchecked")
public static <T> UnaryOperator<T> identityFunction() {
    return (UnaryOperator<T>) IDENTITY_FN;
}

public void UnaryOperator(){
    //no compile error
    UnaryOperator<String> a  = identityFunction();
}
public void UnaryOperator(){
    UnaryOperator<Object> IDENTITY_FN2 = (t) -> t;
    //compile error: can not cast UnaryOperator<Object> to UnaryOperator<String> 
    UnaryOperator<String> b = (UnaryOperator<String>)IDENTITY_FN2;
}

My question is: Doesn't compiler know they are doing the same thing: trying to cast UnaryOperator<Object> to UnaryOperator<String>? What makes the difference?

Upvotes: 0

Views: 71

Answers (1)

Joachim Sauer
Joachim Sauer

Reputation: 308031

The compiler doesn't look at the implementation of that method to see if the cast is correct, it only looks at the type.

A UnaryOperator<Object> is not castable to UnaryOperator<String>.

In your second sample the compiler tells you exactly that.

What does the first code compile then?

Because you're doing what's called an "unchecked cast": You cast a UnaryOperator<Object> to a UnaryOperator<T> and the compiler doesn't at that point know what T is exactly, so it can't check if that's allowed. Usually that kind of cast produces a warning (that you should really take seriously, btw.). But there's an explicit @SuppressWarnings("unchecked") annotation there which tells the compiler to not produce that warning (i.e. "I know what I'm doing").

So the compiler lets you run the code, but notifies you that it can't guarantee the type safety (or tries to, at least).

Upvotes: 3

Related Questions