使用泛型进行运行时类型检查的两个选项:
选项 1 - 损坏构造函数
假设您正在覆盖 indexOf(...),并且只想检查类型的性能,以节省自己迭代整个集合的时间。
像这样制作一个肮脏的构造函数:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
然后,您可以使用 isAssignableFrom 来检查类型。
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
每次实例化对象时,您都必须重复自己:
new MyCollection<Apples>(Apples.class);
你可能会认为这是不值得的。在ArrayList.indexOf(...)的实现中,它们不检查类型是否匹配。
选项 2 - 让它失败
如果你需要使用一个需要未知类型的抽象方法,那么你真正想要的就是编译器停止为实例而哭泣。如果你有这样的方法:
protected abstract void abstractMethod(T element);
你可以这样使用它:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
您将对象强制转换为 T(您的泛型类型),只是为了欺骗编译器。您的强制转换在运行时不执行任何操作,但是当您尝试将错误类型的对象传递到抽象方法中时,您仍然会得到一个 ClassCastException。
注意 1:如果您在抽象方法中执行其他未经检查的强制转换,则 ClassCastExceptions 将被捕获到此处。这可能是好的,也可能是坏的,所以仔细想想。
注意 2:使用 instanceof 时,您将获得免费的空检查。由于您无法使用它,因此您可能需要徒手检查空值。