泛型中的超类型转换(获取泛型类型的通用超类型)

4

这是一个使用Java泛型的简化示例。

void <T> recursiveMethod(T input) {
    //do something with input treating it as type T
    if (/*need to check if T has a supertype*/) {
        recursiveMethod((/*need to get supertype of T*/) input);

        // NOTE that I am trying to call recursiveMethod() with
        // the input object cast as immediate supertype of T.
        // I am not trying to call it with the class of its supertype.
        // Some of you seem to not understand this distinction.
    }
}

如果我们有一个长的类型链 A extends B extends C (extends Object),那么调用 recursiveMethod(new A()) 应该按照以下方式执行:
recursiveMethod(A input)
 -> A has supertype B
recursiveMethod(B input)
 -> B has supertype C
recursiveMethod(C input)
 -> C has supertype Object
recursiveMethod(Object input)
 -> Object has no supertype -> STOP

我可以在不使用泛型的情况下按如下方式完成:

void recursiveMethod(Object input) {
    recursiveMethod(input.getClass(), input);
    }
}

private void recursiveMethod(Class cls, Object input) {
    //do something with input treating it as class 'cls'
    if (cls != null) {
        recursiveMethod(cls.getSuperclass(), input);
    }
}

我能用泛型做同样的事情吗? 我尝试过声明为 <S, T extends S>,然后将其转换为 (S)input,但是 S 总是等于 T,导致出现了堆栈溢出


你有没有考虑执行 input.getClass().getSuperClass() - user902383
你可能误解了用户902383的问题 :) - ADTC
不,我只是给了你一个提示,而不是解决方案。如果你将这个应用到你的“recursiveMethod”中,你就会得到我们的解决方案。 - user902383
@user902383 做得不错,但是你又误解了问题。我不想将超类型 Class 对象传递到 recursiveMethod 中,我想将 input 对象强制转换为其超类型(并在泛型中实现 - 这才是真正的问题)。这是两个非常不同的事情。无论如何,我更喜欢 sp00m 的迭代方法,它运行得很好,而这种递归方法根本不起作用。所以,没有必要再进一步解释了。=) - ADTC
2个回答

3
以下是一种迭代方法,可以解决您的问题:
public static <T> void iterateOverSupertypes(T input) {
    Class<?> clazz = input.getClass();
    while (clazz.getSuperclass() != null) {
        clazz = clazz.getSuperclass();
    }
}

非常有趣!我没有想到迭代!=) - ADTC
如果你不在迭代中调用方法,那么迭代的意义是什么? - arjacsoh
2
请注意,该方法没有必要是泛型的。 - Paul Bellora
@ADTC 我想问一下,因为我见过很多人被绊倒,认为一个接受两个 T 的方法会强制它们成为例如 IntegerInteger。当然,这是对继承工作方式的误解。我建议在方法中也使用 Class<T> 来实际强制执行您想要的内容。但是您显然可以自由决定做什么。 - Paul Bellora
我同意关于误解的观点。无论如何,Class<T>并不是我需要的,因为我需要方法中的实际对象,而不仅仅是它的类(_所讨论的代码相当简化,没有透露实际目的_)。此外,这不会退化为Class<Object>吗?=D - ADTC
显示剩余4条评论

2

当您创建一个新的A并在代码中传递它时,无论您做什么,您的对象始终将是A。

像强制类型转换和泛型这样的东西只是告诉编译器您期望的对象类别的一种方法,但不会以任何方式改变对象的行为。所以我不知道您试图通过“将其视为类型T”来实现什么,但我唯一能想到的实现方法是像您在示例中没有使用泛型那样传递类型。

附言:请记住:Java泛型只是编译器确保类型安全的一种方式,但在编译后的代码中不会有任何痕迹!!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接