(请不要建议我应该抽象X
更多并添加另一种方法。)
在 C++ 中,当我有一个类型的变量x
并且如果它也是类型(作为 的子类)X*
我想做一些特定的事情,我正在写这个:Y*
Y
X
if(Y* y = dynamic_cast<Y*>(x)) {
// now do sth with y
}
同样的事情在 Java 中似乎是不可能的(或者是吗?)。
我已经阅读了这段 Java 代码:
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
有时,当您没有变量x
但它是一个更复杂的表达式时,正是因为这个问题,您需要一个 Java 中的虚拟变量:
X x = something();
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
// x not needed here anymore
(常见的something()
是iterator.next()
。而且你看到你也不能真正调用它两次。你真的需要虚拟变量。)
你在这里根本不需要x
——你只是拥有它,因为你不能instanceof
立即对演员表进行检查。再次将其与相当常见的 C++ 代码进行比较:
if(Y* y = dynamic_cast<Y*>( something() )) {
// ...
}
正因为如此,我引入了一个castOrNull
可以避免虚拟变量的函数x
。我现在可以这样写:
Y y = castOrNull( something(), Y.class );
if(y != null) {
// ...
}
实施castOrNull
:
public static <T> T castOrNull(Object obj, Class<T> clazz) {
try {
return clazz.cast(obj);
} catch (ClassCastException exc) {
return null;
}
}
现在,有人告诉我,以这种方式使用此castOrNull
功能是对. 这是为什么?(或者更笼统地说:你会同意并认为这是邪恶的吗?如果是,为什么会这样?或者你认为这是一个有效的(可能是罕见的)用例吗?)
如前所述,我不想讨论这种沮丧的使用是否是一个好主意。但是让我简要说明一下为什么我有时会使用它:
有时我会遇到这样的情况,即我必须在为非常特定的事物添加另一种新方法(在一种特定情况下仅适用于单个子类)或使用此类
instanceof
检查之间做出选择。基本上,我可以选择添加功能doSomethingVeryVerySpecificIfIAmY()
或进行instanceof
检查。而在这种情况下,我觉得后者更干净。有时我有一些接口/基类的集合,对于所有类型的条目
Y
,我想做一些事情,然后将它们从集合中删除。(例如,我有一个树结构的情况,我想删除所有空叶子的孩子。)