Java:Instanceof 和泛型
在查看值索引的通用数据结构之前,我想看看它是否是 this
已参数化的类型的实例。
但是当我这样做时 Eclipse 会抱怨:
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
这是错误消息:
无法对类型参数 E 执行instanceof 检查。请使用其擦除对象,因为泛型类型信息将在运行时被擦除
更好的方法是什么?
Before I look through my generic data structure for a value's index, I'd like to see if it is even an instance of the type this
has been parametrized to.
But Eclipse complains when I do this:
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
This is the error message:
Cannot perform instanceof check against type parameter E. Use instead its erasure Object since generic type information will be erased at runtime
What is the better way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
错误消息说明了一切。在运行时,类型消失了,无法检查它。
您可以通过为您的对象创建一个工厂来捕获它,如下所示:
然后在对象的构造函数中存储该类型,因此变量,以便您的方法可以如下所示:
The error message says it all. At runtime, the type is gone, there is no way to check for it.
You could catch it by making a factory for your object like this:
And then in the object's constructor store that type, so variable so that your method could look like this:
使用泛型进行运行时类型检查的两个选项:
选项 1 - 破坏构造函数
让我们假设您正在重写 indexOf(...),并且您想要检查类型只是为了性能,以节省自己迭代整个收藏。
制作一个像这样的肮脏的构造函数:
然后你可以使用 isAssignableFrom 检查类型。
每次实例化对象时,您都必须重复自己:
您可能会认为它不值得。在ArrayList.indexOf(...),它们不检查类型是否匹配。
选项 2 - 让它失败
如果您需要使用需要未知类型的抽象方法,那么您真正想要的就是编译器停止抱怨 instanceof。如果你有这样的方法:
你可以这样使用它:
你将对象转换为 T (你的泛型类型),只是为了欺骗编译器。 您的转换在运行时不执行任何操作,但您仍然会当您尝试将错误类型的对象传递到抽象方法时,会出现 ClassCastException。
注意 1:如果您在抽象方法中执行额外的未经检查的强制转换,您的 ClassCastExceptions 将在这里被捕获。这可能是好事,也可能是坏事,所以要三思而后行。
注意2:使用instanceof时,您将获得免费的空检查。由于您无法使用它,因此您可能需要徒手检查是否为 null。
Two options for runtime type checking with generics:
Option 1 - Corrupt your constructor
Let's assume you are overriding indexOf(...), and you want to check the type just for performance, to save yourself iterating the entire collection.
Make a filthy constructor like this:
Then you can use isAssignableFrom to check the type.
Each time you instantiate your object you would have to repeat yourself:
You might decide it isn't worth it. In the implementation of ArrayList.indexOf(...), they do not check that the type matches.
Option 2 - Let it fail
If you need to use an abstract method that requires your unknown type, then all you really want is for the compiler to stop crying about instanceof. If you have a method like this:
You can use it like this:
You are casting the object to T (your generic type), just to fool the compiler. Your cast does nothing at runtime, but you will still get a ClassCastException when you try to pass the wrong type of object into your abstract method.
NOTE 1: If you are doing additional unchecked casts in your abstract method, your ClassCastExceptions will get caught here. That could be good or bad, so think it through.
NOTE 2: You get a free null check when you use instanceof. Since you can't use it, you may need to check for null with your bare hands.
老帖子,但是一种进行通用instanceOf检查的简单方法。
Old post, but a simple way to do generic instanceOf checking.
如果你的类扩展了一个带有泛型参数的类,你也可以在运行时通过反射获取它,然后使用它进行比较,即
在上面的情况下,在运行时你将从 getParameterizedClass() 获取 String.class,并且它会缓存所以在多次检查时你不会得到任何反射开销。请注意,您可以通过 ParameterizedType.getActualTypeArguments() 方法中的索引获取其他参数化类型。
Provided your class extends a class with a generic parameter, you can also get this at runtime via reflection, and then use that for comparison, i.e.
In the case above, at runtime you will get String.class from getParameterizedClass(), and it caches so you don't get any reflection overhead upon multiple checks. Note that you can get the other parameterized types by index from the ParameterizedType.getActualTypeArguments() method.
我遇到了同样的问题,这是我的解决方案(非常谦虚,@george:这次编译并工作......)。
我的探针位于一个实现 Observer 的抽象类中。
Observable 使用可以是任何类型的对象的对象类触发 update(...) 方法。
我只想处理 T 类型的对象
解决方案是将类传递给构造函数,以便能够在运行时比较类型。
对于实现,我们只需将 Class 传递给构造函数
I had the same problem and here is my solution (very humble, @george: this time compiling AND working ...).
My probem was inside an abstract class that implements Observer.
The Observable fires method update(...) with Object class that can be any kind of Object.
I only want to handler Objects of type T
The solution is to pass the class to the constructor in order to be able to compare types at runtime.
For the implementation we just have to pass the Class to the constructor
或者您可能会发现尝试转换为 E 例如
失败。
Or you could catch a failed attempt to cast into E eg.
从技术上讲,您不必这样做,这就是泛型的要点,因此您可以进行编译类型检查:
但是如果您有类层次结构,则 @Override 可能会成为问题。否则请参阅 Yishai 的回答。
Technically you shouldn't have to, that's the point of generics, so you can do compile-type checking:
but then the @Override may be a problem if you have a class hierarchy. Otherwise see Yishai's answer.
对象的运行时类型是一个相对任意的过滤条件。我建议您不要收藏这些肮脏的东西。这可以通过将集合委托给构造中传递的过滤器来简单地实现。
The runtime type of the object is a relatively arbitrary condition to filter on. I suggest keeping such muckiness away from your collection. This is simply achieved by having your collection delegate to a filter passed in a construction.
让Java来判断并捕获异常底线。
Let Java determine it and catch the exception bottom line.