问题
Suppose I have a method
@SuppressWarnings("unchecked")
public <T extends Number> T getNumber() {
try {
return (T)number;
} catch (ClassCastException e) {
return null;
}
}
Assuming number
is an instance of Integer
, invoking method like
Float f = getNumber();
results into a ClassCastException
.
I know (somehow) that this is because of type erasure but could someone provide more profound explanation why the exception escalates up to the assignment level and is not catchable inside method?
NOTE: I do have the version public <T extends Number> T getNumber(Class<T> classT)
that checks the type from classT but was hoping to get rid of passing the classT
and stopped wondering the above problem.
回答1:
After type erasure, return (T)number
becomes return (Number)number
(since Number
is the type bound of T
), which doesn't throw an exception (since number
is an instance of Integer
).
On the other hand, the assignment
Float f = getNumber();
is compiled to
Float f = (Float) getNumber();
since getNumber()
returns a Number
, which can't be assigned to a Float
variable without a cast.
This cast throws the ClassCastException
when getNumber()
is not a Float
.
4.6. Type Erasure
Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables). We write |T| for the erasure of type T. The erasure mapping is defined as follows...
The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
来源:https://stackoverflow.com/questions/47548573/catching-classcastexception-in-a-generic-method-when-doing-generic-cast