假设我有以下课程:
1 2 3 4 5
| public class Test<E> {
public boolean sameClassAs(Object o) {
// TODO help!
}
} |
如何检查o与E是同一类?
1 2 3
| Test<String> test = new Test<String>();
test.sameClassAs("a string"); // returns true;
test.sameClassAs(4); // returns false; |
由于无法覆盖超类,因此无法从(Object o)更改方法签名,因此不要选择我的方法签名。
我也宁愿不尝试尝试强制转换,然后在异常失败时捕获所产生的异常。
Test的实例不了解什么E在运行时。因此,您需要将Class传递给Test的构造函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Test<E> {
private final Class<E> clazz;
public Test(Class<E> clazz) {
if (clazz == null) {
throw new NullPointerException();
}
this.clazz = clazz;
}
// To make things easier on clients:
public static < T > Test< T > create(Class< T > clazz) {
return new Test< T >(clazz);
}
public boolean sameClassAs(Object o) {
return o != null && o.getClass() == clazz;
}
} |
如果需要" instanceof"关系,请使用Class.isAssignableFrom而不是Class比较。注意,出于相同的原因,E将需要是非通用类型,Test需要Class对象。
有关Java API中的示例,请参见java.util.Collections.checkedSet及类似内容。
我一直使用的方法如下。这是一种痛苦并且有点丑陋,但是我还没有找到更好的选择。您必须在构造时传递类类型,因为在编译泛型时,类信息会丢失。
1 2 3 4 5 6 7 8 9
| public class Test<E> {
private Class<E> clazz;
public Test(Class<E> clazz) {
this.clazz = clazz;
}
public boolean sameClassAs(Object o) {
return this.clazz.isInstance(o);
}
} |
我只能使它像这样工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Test<E> {
private E e;
public void setE(E e) {
this.e = e;
}
public boolean sameClassAs(Object o) {
return (o.getClass().equals(e.getClass()));
}
public boolean sameClassAs2(Object o) {
return e.getClass().isInstance(o);
}
} |
我只是想做同样的事情,我刚刚意识到的一个巧妙技巧就是可以尝试强制转换,如果强制转换失败,将抛出ClassCastException。您可以捕获该消息,然后执行任何操作。
因此您的sameClassAs方法应如下所示:
1 2 3 4 5 6 7 8 9 10 11
| public boolean sameClassAs(Object o) {
boolean same = false;
try {
E t = (E)o;
same = true;
} catch (ClassCastException e) {
// same is false, nothing else to do
} finally {
return same;
}
} |