泛型集合中的 ClassCastException 与 instanceOf
ClassCastException vs instanceOf in Generic Collections
我有一个 class 实现了 Collection<E>
。
当我检查我的集合是否包含一个项目时,接口的方法给出一个对象参数,当它必须是一个 <E>
你觉得写这段代码"normal"吗:
@Override
public boolean contains(Object o)
{
E item;
try
{
item=(E) o;
}
catch (ClassCastException e)
{
return false;
}
//check if contains "item"
}
我知道通常使用 try,catch
检查对象的类型是一个糟糕的主意,但在通用集合中我无法使用 instanceOf
检查并且我找不到更好的解决方案。
你可以在这个方法中抛出ClassCastException
,所以你不能检查类型。阅读 Collection 接口的 javadoc。
恕我直言,您应该使用参数对象的 equals / hashCode 方法来检查它是否存在于您的集合中。根本不需要转换或 instanceof。
从 javadoc 它说:
Throws: ClassCastException - if the type of the specified element is incompatible with this collection (optional)
所以完全可以这样编码:
@Override
public boolean contains(Object o) {
T item = (T) o;
// ...
}
如果转换失败则抛出 ClassCastException
。
您当然应该 不 隐藏该异常并安静地 return false
- 这可能会在用户代码中留下许多潜在的错误。
如果您的集合 class 具有 E
作为无边界的通用类型参数,您的检查将毫无用处 -- 强制转换不可能失败,因为完全没有检查演员阵容。 E
,如果它是无界的,则被擦除为 Object
,你的演员表将是 item=(Object) o;
,这不会失败。它可能会导致其他地方的其他失败,但它不能在这里失败,如果以后在其他地方失败,你的 try-catch 也不会捕获它。
你不能使用 instanceof
的事实应该告诉你一些事情 -- instanceof
不能使用的原因是因为它是运行时检查,需要 class在运行时进行检查,而您在运行时没有 class。尝试让演员表失败也是一种运行时检查,因此它根本不会改善您的情况。依靠强制转换失败仅在与 instanceof
相同的情况下有效,因此 NEVER 对 "use a cast because instanceof
doesn't work".
有意义
编写通用代码时,重要的是要考虑代码在类型擦除后的外观。当您将泛型代码擦除为非泛型代码时(通过在适当的地方添加强制转换),代码应该可以正常工作。如果不能将代码写成非泛型,那么它也不能写成泛型。
@Override
public boolean contains(Object o)
{
Object item;
try
{
item= o;
}
catch (ClassCastException e) // does this make sense?
{
return false;
}
//check if contains "item"
}
我有一个 class 实现了 Collection<E>
。
当我检查我的集合是否包含一个项目时,接口的方法给出一个对象参数,当它必须是一个 <E>
你觉得写这段代码"normal"吗:
@Override
public boolean contains(Object o)
{
E item;
try
{
item=(E) o;
}
catch (ClassCastException e)
{
return false;
}
//check if contains "item"
}
我知道通常使用 try,catch
检查对象的类型是一个糟糕的主意,但在通用集合中我无法使用 instanceOf
检查并且我找不到更好的解决方案。
你可以在这个方法中抛出ClassCastException
,所以你不能检查类型。阅读 Collection 接口的 javadoc。
恕我直言,您应该使用参数对象的 equals / hashCode 方法来检查它是否存在于您的集合中。根本不需要转换或 instanceof。
从 javadoc 它说:
Throws: ClassCastException - if the type of the specified element is incompatible with this collection (optional)
所以完全可以这样编码:
@Override
public boolean contains(Object o) {
T item = (T) o;
// ...
}
如果转换失败则抛出 ClassCastException
。
您当然应该 不 隐藏该异常并安静地 return false
- 这可能会在用户代码中留下许多潜在的错误。
如果您的集合 class 具有 E
作为无边界的通用类型参数,您的检查将毫无用处 -- 强制转换不可能失败,因为完全没有检查演员阵容。 E
,如果它是无界的,则被擦除为 Object
,你的演员表将是 item=(Object) o;
,这不会失败。它可能会导致其他地方的其他失败,但它不能在这里失败,如果以后在其他地方失败,你的 try-catch 也不会捕获它。
你不能使用 instanceof
的事实应该告诉你一些事情 -- instanceof
不能使用的原因是因为它是运行时检查,需要 class在运行时进行检查,而您在运行时没有 class。尝试让演员表失败也是一种运行时检查,因此它根本不会改善您的情况。依靠强制转换失败仅在与 instanceof
相同的情况下有效,因此 NEVER 对 "use a cast because instanceof
doesn't work".
编写通用代码时,重要的是要考虑代码在类型擦除后的外观。当您将泛型代码擦除为非泛型代码时(通过在适当的地方添加强制转换),代码应该可以正常工作。如果不能将代码写成非泛型,那么它也不能写成泛型。
@Override
public boolean contains(Object o)
{
Object item;
try
{
item= o;
}
catch (ClassCastException e) // does this make sense?
{
return false;
}
//check if contains "item"
}