Nic*_*ner 127 java generics instanceof typechecking
在我查看值的索引的通用数据结构之前,我想看看它是否this
已经参数化的类型的实例.
但是当我这样做时Eclipse会抱怨:
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
无法对类型参数E执行instanceof检查.请改为使用其擦除对象,因为泛型类型信息将在运行时被擦除
有什么更好的方法呢?
Yis*_*hai 76
错误消息说明了一切.在运行时,类型消失了,无法检查它.
您可以通过为您的对象创建工厂来捕获它,如下所示:
public static <T> MyObject<T> createMyObject(Class<T> type) {
return new MyObject<T>(type);
}
Run Code Online (Sandbox Code Playgroud)
然后在对象的构造函数存储中输入类型,这样变量使得您的方法看起来像这样:
if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass()))
{
return -1;
}
Run Code Online (Sandbox Code Playgroud)
Sha*_*ley 38
使用泛型进行运行时类型检查的两个选项:
选项1 - 破坏您的构造函数
让我们假设您重写indexOf(...),并且您想要检查类型的性能,以节省自己迭代整个集合.
像这样做一个肮脏的构造函数:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用isAssignableFrom检查类型.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Run Code Online (Sandbox Code Playgroud)
每次实例化对象时,都必须重复自己:
new MyCollection<Apples>(Apples.class);
Run Code Online (Sandbox Code Playgroud)
你可能认为它不值得.在ArrayList.indexOf(...)的实现中,它们不检查类型是否匹配.
选项2 - 让它失败
如果您需要使用需要未知类型的抽象方法,那么您真正想要的就是让编译器停止对instanceof的哭泣.如果您有这样的方法:
protected abstract void abstractMethod(T element);
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
Run Code Online (Sandbox Code Playgroud)
您正在将对象转换为T(您的泛型类型),只是为了欺骗编译器.您的转换在运行时不执行任何操作,但是当您尝试将错误类型的对象传递到抽象方法时,仍会得到ClassCastException.
注意1:如果您在抽象方法中执行其他未经检查的强制转换,则此类ClassCastExceptions将被捕获.这可能是好事也可能是坏事,所以请仔细考虑.
注意2:使用instanceof时,您将获得免费的空值检查.由于您无法使用它,您可能需要赤手检查null.
Jon*_*sen 14
旧帖子,但是通用instanceOf检查的简单方法.
public static <T> boolean isInstanceOf(Class<T> clazz, Class<T> targetClass) {
return clazz.isInstance(targetClass);
}
Run Code Online (Sandbox Code Playgroud)
小智 12
如果您的类使用泛型参数扩展了一个类,您也可以通过反射在运行时获取它,然后使用它进行比较,即
class YourClass extends SomeOtherClass<String>
{
private Class<?> clazz;
public Class<?> getParameterizedClass()
{
if(clazz == null)
{
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
clazz = (Class<?>)pt.getActualTypeArguments()[0];
}
return clazz;
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,在运行时,您将从getParameterizedClass()获取String.class,并且它会缓存,因此您不会在多次检查时获得任何反射开销.请注意,您可以通过ParameterizedType.getActualTypeArguments()方法的索引获取其他参数化类型.
我有同样的问题,这是我的解决方案(非常谦虚,@ george:这次编译和工作......).
我的probem在一个实现Observer的抽象类中.Observable使用Object类触发方法update(...),Object类可以是任何类型的Object.
我只想处理T类型的对象
解决方案是将类传递给构造函数,以便能够在运行时比较类型.
public abstract class AbstractOne<T> implements Observer {
private Class<T> tClass;
public AbstractOne(Class<T> clazz) {
tClass = clazz;
}
@Override
public void update(Observable o, Object arg) {
if (tClass.isInstance(arg)) {
// Here I am, arg has the type T
foo((T) arg);
}
}
public abstract foo(T t);
}
Run Code Online (Sandbox Code Playgroud)
对于实现,我们只需将Class传递给构造函数
public class OneImpl extends AbstractOne<Rule> {
public OneImpl() {
super(Rule.class);
}
@Override
public void foo(Rule t){
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
或者你可以抓住一个失败的尝试投射到E 例如.
public int indexOf(Object arg0){
try{
E test=(E)arg0;
return doStuff(test);
}catch(ClassCastException e){
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
156307 次 |
最近记录: |