首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么Java不允许Throwable的泛型子类?

为什么Java不允许Throwable的泛型子类?
EN

Stack Overflow用户
提问于 2009-02-01 18:07:52
回答 6查看 35.4K关注 0票数 168

根据Java Language Sepecification,第3版:

It is a compile-time error if a generic class is a direct or indirect subclass of Throwable.

我想知道为什么会做出这样的决定。泛型异常有什么问题?

(据我所知,泛型只是编译时的语法糖,它们无论如何都会在.class文件中转换为Object,因此有效地声明泛型类就好像其中的所有内容都是Object一样。如果我错了,请纠正我。)

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-02-01 18:22:42

正如mark所说的,类型是不可重用的,这在以下情况下是一个问题:

代码语言:javascript
复制
try {
   doSomeStuff();
} catch (SomeException<Integer> e) {
   // ignore that
} catch (SomeException<String> e) {
   crashAndBurn()
}

SomeException<Integer>SomeException<String>都被擦除为同一类型,因此无法区分异常实例,因此也无法判断应该执行哪个catch块。

票数 174
EN

Stack Overflow用户

发布于 2009-02-01 18:11:05

下面是一个如何使用异常的简单示例:

代码语言:javascript
复制
class IntegerExceptionTest {
  public static void main(String[] args) {
    try {
      throw new IntegerException(42);
    } catch (IntegerException e) {
      assert e.getValue() == 42;
    }
  }
}

TRy语句体抛出具有给定值的异常,该异常由catch子句捕获。

相反,禁止使用下面的新异常定义,因为它创建了一个参数化类型:

代码语言:javascript
复制
class ParametricException<T> extends Exception {  // compile-time error
  private final T value;
  public ParametricException(T value) { this.value = value; }
  public T getValue() { return value; }
}

尝试编译上述代码时会报告错误:

代码语言:javascript
复制
% javac ParametricException.java
ParametricException.java:1: a generic class may not extend
java.lang.Throwable
class ParametricException<T> extends Exception {  // compile-time error
                                     ^
1 error

此限制是合理的,因为几乎任何捕获此类异常的尝试都会失败,因为该类型是不可重构的。人们可能会期望异常的典型用法如下所示:

代码语言:javascript
复制
class ParametricExceptionTest {
  public static void main(String[] args) {
    try {
      throw new ParametricException<Integer>(42);
    } catch (ParametricException<Integer> e) {  // compile-time error
      assert e.getValue()==42;
    }
  }
}

这是不允许的,因为catch子句中的类型是不可重复的。在撰写本文时,Sun编译器在这种情况下报告了一系列语法错误:

代码语言:javascript
复制
% javac ParametricExceptionTest.java
ParametricExceptionTest.java:5: <identifier> expected
    } catch (ParametricException<Integer> e) {
                                ^
ParametricExceptionTest.java:8: ')' expected
  }
  ^
ParametricExceptionTest.java:9: '}' expected
}
 ^
3 errors

因为异常不能是参数化的,所以语法受到限制,因此类型必须写为标识符,不能有以下参数。

票数 16
EN

Stack Overflow用户

发布于 2015-02-09 19:21:21

这本质上是因为它的设计方式很糟糕。

这个问题妨碍了干净的抽象设计,

代码语言:javascript
复制
public interface Repository<ID, E extends Entity<ID>> {

    E getById(ID id) throws EntityNotFoundException<E, ID>;
}

catch子句不会因为泛型没有具体化而失败,这不是借口。编译器可以简单地禁止扩展Throwable的具体泛型类型,或者禁止catch子句中的泛型。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/501277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档