Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.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块中执行catch Bouncy和Bouncy,但是如果我们在不相交的上下文中使用它们,并且有严格的编译时可执行规则(这与泛型现在的工作方式非常相似),那么这不是可行的吗?Java语言规范 : 由于Java虚拟机的捕获机制仅适用于非泛型类,因此需要此限制 就我个人而言,我认为这是因为在catch子句中我们无法获得泛型的任何好处。由于类型擦除,我们无法编写catch(Bouncy-ex),但是如果我们编写catch(Bouncy-ex)

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

Java语言规范 :

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


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

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

void process(List<String> list) {
}

void process(List<Integer> list) {
}

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

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

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

    界面弹性{

    /…

    }

    类BouncyString扩展异常实现弹性{

    /…

    }
  • 抛出
    子句可以引用类型参数,例如。
    静态无效

    throwIfInstanceOf(Throwable ex,Class clazz)抛出X{

    if(clazz.isInstance(ex))抛出clazz.cast(ex);

    }

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

    长答案:正如其他人已经指出的,由于擦除,在运行时“catch MyException”和“catch MyException”之间没有区别

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

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

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

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

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

    class MyException<T> {}
    ...
    catch (MyException e) { // raw
    
    类MyException{}
    ...
    捕获(MyException e){
    
    知道为什么会这样吗?抱歉,但我不能完全理解JLS中的参数。好像这条语句忘记了编译器执行类型擦除,在JVM使用其捕获机制时有效地删除了泛型。那么,如果语法糖没有impa,那么如何避免语法糖呢因为它将被删除,所以在运行时使用ct?在这种情况下,为什么不禁止下面我自己的答案中的例子呢?我的意思是,JVM在这些上下文中也不支持泛型,但它们在源代码中是允许的。:)感谢您承认“类型擦除后冲突”中的弱点论点——我觉得它太容易被接受为限制的原因,所以我自己承担起了抗争的责任。当然,这也意味着被接受的答案也是误导性的,可能需要更正。我的一些例子可能会让人困惑。当我给出两个方法签名的例子时,它们会删除到同一个签名e、 我引用了一些真实的例子,如果出现无效的情况,兼容编译器必须拒绝编译。我只是指出这些情况(对相同泛型类型的擦除)语言设计者没有将它们作为全面禁止泛型的前提,但它们似乎被用来禁止抛出子句中的泛型。相反,编译器被要求识别并报告此类情况。它本可以对catch子句执行相同的操作。选择似乎是任意的。语句“catch(Foo-ex)”大约在“if-ex-instanceof-Foo”;类型擦除使得无法将其与“if-ex-instanceof-Foo”区分开来。虽然列表和列表在运行时与非泛型API配合很好;但在编译时类型信息尚未擦除,因此允许泛型返回或设置。我相信您的前提是有缺陷的。为什么
    catch(Foo-ex)
    需要解释为
    if(ex instanceof Foo)
    ?编译器可以执行类型擦除,运行时将捕获解释为
    if(ex instanceof Foo)
    。运行时将像今天一样工作,但由于一般异常,我们将有更好的编译时支持。当然,在同一上下文中不可能同时捕获
    Foo
    Foo
    ,但这没关系:今天的方法参数也一样糟糕,因为不能同时捕获
    Foo(列表)
    foo(List)
    在相同的上下文中。是的,不可能区分foo和foo,这是不正常的。当我捕获IOException时,我只想捕获它,而不是IOException。现在使用的解决方法是有特定的异常(FileNotFound,ReadTimeout)如果需要,可以分别捕获它们中的每一个。通过向我们展示一个使用标准异常类的精心设计的示例,您坚持认为在异常类中支持泛型需要运行时泛型。如果Java支持泛型异常——对我来说很明显,在理论上支持这些——我们将泛型类型参数用于更普通的事情。您必须开始了解泛型的含义:语法suga
    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) {