【发布时间】:2017-03-10 03:46:11
【问题描述】:
我想知道是否有办法检查引用是否已转换为其对象的确切类型。比如……
String s = new String("test");
checkCast(s); //Returns true, since s has a dynamic and static type of String.
Object o = (Object) s;
checkCast(o); //Returns false, since the dynamic and static type of o are not equal.
关于实际问题的一些背景...
我有一个 A、B 和 C 类的层次结构,如下所示:
class A {}
class B extends A {}
class C extends B {}
然后我有一个 LinkedList<A> 的 A 对象。此列表可能包含上述任何类。然后我有一个这样的方法......
<T extends A> T getFirstObjInList(){
//Iterate over the list and return the first object that is of type T...
}
我需要知道如何检查列表中的对象是否属于传递给方法的通用类型。我不能使用 instanceof,因为擦除等,我真的更喜欢不要更改方法的标题,即添加任何参数或类似的东西。
我首先尝试在 for 循环中将列表中的每个对象强制转换为 T,如果抛出 ClassCastException,继续迭代,但这显然不适用于我拥有的层次结构,所以现在我寻找一种方法来检查一个对象是否已被强制转换为它的动态类型。 如果列表中的对象是指定的类型,那么在强制转换时,它的静态类型不会改变,所以如果我可以比较这两种类型,我就可以确定对象是否是一个实例给定的泛型类型。
注意:list.getFirst() instanceof T 由于类型擦除而无法编译。
【问题讨论】:
-
这个问题闻起来像XY Problem,当最好的解决方案是使用完全不同的方法时,你会问如何解决特定的代码问题。最好告诉我们您正在尝试解决的总体问题,而不是您当前尝试解决的方式。
-
我本来打算推荐instanceof,但你说那是因为擦除了……你真的测试过吗?无论如何,为了扩展@HovercraftFullOfEels 所说的内容,如果您正在检查类然后为不同的类执行不同的行为,您可能应该使用多态性以更简洁的方式实现相同的结果。
-
你的方法,即使你可以让它发挥作用,看起来也很脆弱,因此很容易被打破。如果@Maybe_Factor 建议的简单多态性还不够,那么您应该研究更高程度的间接性,例如可以通过使用设计模式获得。访问者模式可能就是您正在寻找的。span>
-
@YorickIsTheBest 我不确定多态性在这种情况下是否合适,但有时我们会看到人们使用对象的类型来决定要做什么,从而导致一些带有一堆 instanceof 的 if 语句在条件。我很好奇您是否可以修改 shmosel 的答案以使用 T.getClass() 而不必传入类型参数?
-
@Maybe_Factor 你的意思可能是
T.class,它在 Java 中是无效的,因为类型擦除。