通用助手方法与直接类铸造?

时间:2016-02-21 08:42:31

标签: java generics

我现在正在做什么?像这样。

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);
}

哪种方法更好?

2 个答案:

答案 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.classtype == SubtypeOfSome.class会失败。 <T super Some>是安全的(类型是obj的消费者)。

第二种方法更好,因为虽然您必须进行强制转换(因为obj.getClass()类型为Class<? extends T>),但它可以安全地转换为Class<T>,因为它是直接从obj推导出来的{1}}。

从提供的代码中可以明显看出,但为什么需要重载?为什么// for brevity无法实现doSome(T obj)