我现在正在做什么?像这样。
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);
}
哪种方法更好?
答案 0 :(得分:1)
第一种方式更好,因为所有类型在理论层面都是正确的。
在第二种方式中,演员(Class<T>) obj.getClass()
在理论上是不正确的。 obj
的实际运行时类可以是T
的任何子类型,因此obj.getClass()
可以是Class<some subtype of T>
,与Class<T>
不兼容。由于类型擦除,演员在运行时实际上失败了,但你不应该编写理论上不正确的代码。
答案 1 :(得分:0)
在第一种方法的doSomeHelper
中,type.cast(obj)
不安全,因为obj.getClass() == Some.class
和type == SubtypeOfSome.class
会失败。 <T super Some>
是安全的(类型是obj的消费者)。
第二种方法更好,因为虽然您必须进行强制转换(因为obj.getClass()
类型为Class<? extends T>
),但它可以安全地转换为Class<T>
,因为它是直接从obj
推导出来的{1}}。
从提供的代码中可以明显看出,但为什么需要重载?为什么// for brevity
无法实现doSome(T obj)
?