我目前是这样做的。
static <T extends Some> T doSome(Class<T> type, T obj) {
// pre-existing legacy method
// omitted for brevity
}
private static <T extends Some> T doSomeHelper(Class<T> type, Some obj) {
// private!
// only invoked from doSome(T)
return doSome(type, type.cast(obj));
}
@SuppressWarnings("unchecked")
static <T extends Some> T doSome(T obj) {
return (T) doSomeHelper(obj.getClass(), obj);
}
我刚刚发现以下方法对编译器也没有问题。
@SuppressWarnings("unchecked")
public static <T extends Some> T doSome_(T obj) {
return doSome((Class<T>) obj.getClass(), obj);
}
哪种方法更好?
第一种方法更好,因为所有类型在理论层面上都是正确的。
第二种方式,演员(Class<T>) obj.getClass()
在理论上是不正确的。 obj
的实际运行时类可以是T
的任何子类型,因此obj.getClass()
可以是Class<some subtype of T>
的,这与Class<T>
不兼容。由于类型擦除,强制转换实际上不会在运行时失败,但您不应编写理论上不正确的代码。
在第一种方法doSomeHelper
中,type.cast(obj)
不安全,因为如果obj.getClass() == Some.class
和type == SubtypeOfSome.class
,它将失败。 <T super Some>
将是安全的(类型是 OBJ 的使用者)。
第二种方法更好,因为尽管您必须进行强制转换(因为obj.getClass()
是 Class<? extends T>
类型),但由于它直接派生自 obj
,因此可以安全地铸造Class<T>
。
但是,从提供的代码中看不出为什么需要重载 - 为什么不能// for brevity
doSome(T obj)
实现?