Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java不支持通用的一次性软件?_Java_Generics_Oop_Throwable - Fatal编程技术网

为什么Java不支持通用的一次性软件?

为什么Java不支持通用的一次性软件?,java,generics,oop,throwable,Java,Generics,Oop,Throwable,当然,我们没有它也能过得去。我并不是说我们应该能够在同一个try块中捕获Bouncy和Bouncy,但是如果我们在不相交的上下文中使用它们,并且有严格的编译时可执行规则,这与泛型现在的工作方式非常相似,那么这不是可行的吗?Java语言规范 : 由于Java虚拟机的捕获机制仅适用于非泛型类,因此需要此限制 就我个人而言,我认为这是因为在catch子句中我们不能得到泛型的任何好处。由于类型擦除,我们无法编写catch-Bouncy-ex,但如果我们编写catch-Bouncy-ex,则将其设置为泛型

当然,我们没有它也能过得去。我并不是说我们应该能够在同一个try块中捕获Bouncy和Bouncy,但是如果我们在不相交的上下文中使用它们,并且有严格的编译时可执行规则,这与泛型现在的工作方式非常相似,那么这不是可行的吗?

Java语言规范 :

由于Java虚拟机的捕获机制仅适用于非泛型类,因此需要此限制


就我个人而言,我认为这是因为在catch子句中我们不能得到泛型的任何好处。由于类型擦除,我们无法编写catch-Bouncy-ex,但如果我们编写catch-Bouncy-ex,则将其设置为泛型将毫无用处。

类型擦除。运行时异常类型没有泛型信息。因此你不能这样做


当Java从1.4迁移到1.5时,类型擦除是如何决定保持向后兼容性的。当时很多人都不快乐,这是理所当然的。但考虑到已部署代码的数量,打破1.4中运行良好的代码是不可想象的。

以下是您可以做的几件事:

throwable可以实现泛型接口,只要throwable本身没有类型参数,例如

界面弹性{ // ... } 类BouncyString扩展异常实现了BouncyString{ // ... } throws子句可以引用类型参数,例如。 静态空隙 通过Finstanceofthrowable ex,clazz类抛出X{ 如果clazz.isinstancex抛出clazz.castex; }


简短回答:因为他们走捷径,就像他们在擦除时做的那样

长答案:正如其他人已经指出的,由于擦除,在运行时无法在catch-MyException和catch-MyException之间做出区别

但这并不意味着不需要一般例外。我希望泛型能够使用泛型字段!它们可以简单地允许泛型异常,但只允许在原始状态下捕获它们,例如catch MyException

当然,这将使泛型更加复杂。
这是为了说明删除泛型的决定有多糟糕。什么时候我们会有一个支持RTTI的真正泛型的Java版本,而不是当前的语法糖?

您仍然可以使用泛型方法,如下所示:

catch( Mistake ea ) {
  ...
}
因为这行不通:

catch (Exception<T1> e) {}
Java本可以毫无问题地完成整个过程:

class MyException<T> {}
...
catch (MyException e) { // raw

你知道为什么会这样吗?对不起,但是我不知道JLS中的论点。这就好像该语句忘记了编译器执行类型擦除,从而在JVM使用其捕获机制时有效地删除了泛型。那么,如果语法糖对运行时没有任何影响,因为它将被删除,那么如何避免语法糖呢?在这种下滑的情况下,为什么不禁止其他例子,比如下面我自己的文章中的例子呢?我的意思是,JVM在这些上下文中也不支持泛型,但它们在源代码中是允许的感谢您承认类型擦除后冲突论点中的弱点——我觉得它太容易被接受为限制的原因,所以我自己承担了与之抗争的责任。当然,这也意味着被接受的答案也是误导性的,可能应该予以纠正。我的一些例子可能会令人困惑。当我给出两个删除同一签名的方法签名的例子时,我指的是实际的例子,如果在无效情况下兼容编译器必须拒绝编译。我只是指出,这些情况下,对同一泛型类型的擦除并没有被语言设计者用作全面禁止泛型的前提,但它们似乎被用来禁止子句中的泛型。相反,编译器被要求识别并报告此类案例。对于catch子句,它也可以这样做。选择似乎是任意的。语句catch Foo ex的执行就好像Foo的ex instanceof;类型擦除使得无法区分它是否为Foo的exinstanceof。List和List虽然在运行时与非泛型API配合良好;在编译时,类型信息还没有被删除,因此泛型可以返回或设置。我相信你的前提是有缺陷的。为什么catch Foo ex需要被解释为Foo的ex instanceof?编译器可以执行类型擦除,运行时将解释catch,就好像是Foo的exinstanceof。运行时将像今天一样工作,但由于通用异常,我们将有更好的编译时支持。当然,在同一上下文中捕获Foo和Foo是不可能的,但这没关系:今天的方法参数也一样糟糕,因为不能在同一上下文中同时包含傻瓜和傻瓜。是的,不可能区分Foo和Foo,这是不好的。当我捕获IOException时,我只想捕获它,而不是IOException。现在使用的解决方法是使用特定的异常FileNotFound、ReadTimeout wh
您坚持在异常类中支持泛型需要运行时泛型,向我们展示了一个使用标准异常类的精心设计的示例。如果Java支持泛型异常——对我来说,很明显,在理论上支持这些异常是可能的——那么我们会将泛型类型参数用于更普通的事情。您必须开始了解泛型的本质:语法糖,以及编译器对查找类型不匹配错误的支持。对运行时没有影响。没有人说核心异常类也必须改变。引入真正的泛型而不破坏现有代码的一种方法是引入注释@RealGeneric,它在编译时将类型信息捕获到注释中,在我看来,如果将两个catch块擦除为同一类型,那么擦除可能会导致冲突的观点是有缺陷的,请参阅我的答案。如果将两个catch块擦除为同一类型,您仍然可以在catch块中允许泛型并生成编译器错误。编译器现在对方法参数执行此操作:如果您编写void processList{},编译器不会抱怨-它只是将其擦除到processList。如果添加读取void processList{}的同级,编译器会突然生成错误。在下一篇评论中继续。。。catch块也可以这样做:允许catchMyException,除非我还添加了catchMyException。如果我需要添加第二个catch呢?这将比不允许任何泛型异常的简单决定更加令人困惑。而且,如果我只有一个Foo类,并添加了一个catchFoo语句,然后John创建了Foo,而该异常是从代码中抛出的。。。运行时怎么知道它不会在我的捕获中捕获它?字体已被删除。那将成为地狱的一个版本。对于方法,尽管这种冲突在编译时是已知的;对于catch来说,这是不可能找到的。关于这个答案的反驳,请参阅我的答案。此外,向后兼容性问题并没有阻止它们在其他上下文中允许泛型。你们不会听到有人抱怨列表不能被泛化,因为我们需要保持向后兼容性。你听到的是泛型在被称为类型擦除的过程中被擦除,以保持向后兼容性。对于异常也可以这样做。请不要混淆未执行类型擦除的编译器和已执行类型擦除的运行时的可用信息。运行时catch语句无法区分一个泛型异常和另一个泛型异常,而编译器具有泛型信息,但稍后会将其删除。我还说,这不是不允许一般例外的理由。这是不允许擦除为同一类型的catch块的原因之一,但仅此而已。无法在其专门化中捕获的泛型异常只有一点实用价值。这是一个比不能在同一上下文中捕获Ex和Ex的语句更好的参数。但举例来说:一个可以从整个域模型通用地管理对象的框架可能会抛出一个通用异常类ValidationException。一般异常处理程序可能希望捕获ValidationException,但更具体的处理程序可能知道类型并使用ValidationException。今天的情况是,我可能不得不显式地强制转换,而失去了语法。不管怎样,就像我说的,这听起来比其他论点好得多。准备好其他的选择。您还可以在exception类中使用泛型方法。如@suppressWarningUnchecked public T getObject{return T object;}。
catch( Mistake ea ) {
  ...
}
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();
}
catch (Exception<T1> e) {}
List<T1> list;
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);
}
class MyException<T> {}
...
catch (MyException e) { // raw
class MyException<T> {}
...
catch (MyException<Foo> e) {