当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《为什么Java不允许Throwable的泛型子类?》经验,为你挑选了3个好方法。

根据Java语言规范,第3版:

如果泛型类是其直接或间接子类,则为编译时错误Throwable.

我希望理解为什么做出这个决定.通用异常有什么问题?

(据我所知,泛型只是编译时的语法糖,他们将被翻译成Object反正在.class文件,因此有效地声明一个泛型类是仿佛一切都在它是一个Object,请纠正我,如果我错了.)



1> Torsten Mare..:

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

try {
   doSomeStuff();
} catch (SomeException e) {
   // ignore that
} catch (SomeException e) {
   crashAndBurn()
}

SomeExceptionSomeException被擦除至相同类型的,也没有办法为JVM区分异常情况,因此没有办法知道哪些catch应该被执行的块.


因此规则不应该是"泛型类型不能子类Throwable",而是"catch子句必须始终使用原始类型".
@ SuperJedi224 - 没有.它确实正确 - *考虑到仿制药**必须向后兼容的约束.*
但"可再生"意味着什么?
他们可能只是禁止使用两个相同类型的捕获块.因此单独使用SomeExc 是合法的,只使用SomeExc 和SomeExc 一起是非法的.这不会有任何问题,或者是吗?
哦,现在我明白了.我的解决方案会导致RuntimeExceptions出现问题,而不必声明.因此,如果SomeExc是RuntimeException的子类,我可以抛出并显式捕获SomeExc ,但也许其他一些函数默默地抛出SomeExc ,而SomeExc 的catch块也会意外地捕获它.

2> IAdapter..:

以下是如何使用异常的简单示例:

class IntegerExceptionTest {
  public static void main(String[] args) {
    try {
      throw new IntegerException(42);
    } catch (IntegerException e) {
      assert e.getValue() == 42;
    }
  }
}

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

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

class ParametricException extends Exception {  // compile-time error
  private final T value;
  public ParametricException(T value) { this.value = value; }
  public T getValue() { return value; }
}

尝试编译上述报告错误:

% javac ParametricException.java
ParametricException.java:1: a generic class may not extend
java.lang.Throwable
class ParametricException extends Exception {  // compile-time error
                                     ^
1 error

这种限制是明智的,因为几乎任何捕获此类异常的尝试都必须失败,因为该类型不可恢复.有人可能会认为异常的典型用法如下:

class ParametricExceptionTest {
  public static void main(String[] args) {
    try {
      throw new ParametricException(42);
    } catch (ParametricException e) {  // compile-time error
      assert e.getValue()==42;
    }
  }
}

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

% javac ParametricExceptionTest.java
ParametricExceptionTest.java:5:  expected
    } catch (ParametricException e) {
                                ^
ParametricExceptionTest.java:8: ')' expected
  }
  ^
ParametricExceptionTest.java:9: '}' expected
}
 ^
3 errors

由于异常不能参数化,因此语法受到限制,因此必须将类型写为标识符,而不包含以下参数.


当你说'可兑换'时你是什么意思?'可再生'不是一个字.

3> 小智..:

这主要是因为它的设计方式很糟糕.

此问题可防止干净的抽象设计,例如

public interface Repository> {

    E getById(ID id) throws EntityNotFoundException;
}

一个catch子句因泛型而失败的事实并没有被证实是没有任何借口的.编译器可以简单地禁止在catch子句中扩展Throwable或禁止泛型的具体泛型类型.

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有