您仍然可以使用泛型方法,如下所示:
public class SomeException {
private final Object target;
public SomeException(Object target) {
this.target = target;
}
public <T> T getTarget() {
return (T) target;
}
}
....
catch (SomeException e) {
Integer target = e.getTarget();
}
我同意克里斯蒂安的上述回答。虽然公认的答案在技术上是正确的(就其引用 JVM 规范而言),但 Cristian Vasile 的答案是符合甚至挑战限制的答案。
我在回答这个问题时指出了至少两个我不同意并且我将反驳的论点。如果这些答案中的论点是正确的,我们可以使用这些论点在今天成功使用它们的其他上下文中攻击泛型。
第一个参数声明我们不能使用这个:
catch (Exception<T1> e) {}
因为 JVM 不知道如何使用 Exception<T1>。这个论点似乎也在攻击泛型的这种使用,因为 JVM 不知道如何使用List<T1>:
List<T1> list;
当然,该参数忘记了编译器执行类型擦除,因此 JVM 不需要知道如何处理 Exception<T1>。它可以简单地处理Exception,就像它处理List一样。
当然,由于类型擦除,我们永远无法在同一个 try/catch 中处理 catch(Exception<T1> e) 和 catch(Exception<T2> e),但话又说回来,这并不比今天使用方法参数或返回值更糟糕:我们不处理 @ 987654331@ 和 myMethod(List<T2>) 今天也可以……(我在下面的第二次反驳中重申了这一点。)
第二个参数如下。我们不允许这样做:
catch (Exception<T1> e) {}
因为这行不通:
catch (Exception<T1> e) {}
catch (Exception<T2> e) {}
好的,那为什么不禁止这个:
interface MyInterface {
Comparable<Integer> getComparable();
}
因为这不起作用:
interface MyInterface {
Comparable<Integer> getComparable();
Comparable<String> getComparable();
}
或者这个:
interface MyInterface {
void setComparable(Comparable<Integer> comparable);
}
因为这不起作用:
interface MyInterface {
void setComparable(Comparable<Integer> comparable);
void setComparable(Comparable<String> comparable);
}
换句话说,为什么在大多数情况下不禁止泛型?
第二个论点忘记了,尽管我们不可能允许在这些上下文中擦除到相同非泛型构造的不同泛型构造,但我们仍然可以做次优的事情,并且允许泛型只要类型不会擦除为相同的类型。这就是我们对方法参数所做的事情:我们允许您使用泛型,但一旦我们在类型擦除后检测到重复签名就会抱怨。好吧,我们可以用异常和 catch 块做同样的事情......
最后,我将扩展 Cristian 的答案。而不是允许通用异常类和使用catch块中的原始类型:
class MyException<T> {}
...
catch (MyException e) { // raw
Java 完全可以毫无问题地完成:
class MyException<T> {}
...
catch (MyException<Foo> e) {