Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.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
C#vs Java泛型_C#_Java_Generics_Comparison - Fatal编程技术网

C#vs Java泛型

C#vs Java泛型,c#,java,generics,comparison,C#,Java,Generics,Comparison,我听说泛型的Java实现不如C#实现好。语法看起来很相似,Java实现中有什么不符合标准,或者是宗教观点?差异可以归结为Microsoft和Sun的设计决策 由编译器通过实现,这意味着类型检查在编译时发生,类型信息被删除。采用这种方法是为了使遗留代码与使用泛型的新代码兼容: 在Java教程中: 在实例化泛型类型时, 编译器通过 一种称为类型擦除的技术-a 编译器删除所有 与类型参数相关的信息 和类或类中的类型参数 方法。类型擦除支持Java 使用泛型的应用程序 保持与的二进制兼容性 Java库和

我听说泛型的Java实现不如C#实现好。语法看起来很相似,Java实现中有什么不符合标准,或者是宗教观点?

差异可以归结为Microsoft和Sun的设计决策

由编译器通过实现,这意味着类型检查在编译时发生,类型信息被删除。采用这种方法是为了使遗留代码与使用泛型的新代码兼容:

在Java教程中:

在实例化泛型类型时, 编译器通过 一种称为类型擦除的技术-a 编译器删除所有 与类型参数相关的信息 和类或类中的类型参数 方法。类型擦除支持Java 使用泛型的应用程序 保持与的二进制兼容性 Java库和应用程序 是在泛型之前创建的

但是,对于,编译器不会擦除类型,并且类型检查是在运行时执行的。这样做的好处是类型信息保留在编译代码中

来自维基百科:

此设计选择可用于 提供附加功能,例如 允许反射 保留泛型类型,以及 减轻了一些限制 指擦除(例如无法 创建通用数组)。这 也就是说没有 运行时强制转换和 通常昂贵的拳击转换

与其说“.NET泛型比Java泛型好”,不如研究实现泛型方法的差异。在Java中,保持兼容性似乎是一个高优先级,而在.NET中(在2.0版中引入时),实现使用泛型的全部好处是一个更高优先级。

在消除差异方面做了大量工作。然而,快速而肮脏的总结是

在语法和用法方面。两种语言的语法大致相同。这里和那里的一些怪癖(最显著的是约束)。但基本上,如果你能阅读其中一个,你就可以阅读/使用另一个

但最大的区别在于实现上

Java使用类型擦除的概念来实现泛型。简而言之,底层编译类实际上不是泛型的。它们编译到对象并强制转换。实际上,Java泛型是一个编译时工件,在运行时很容易被破坏

另一方面,借助CLR,实现泛型直到字节码。为了支持2.0中的泛型,CLR进行了一些突破性的更改。其好处是性能改进、深层安全验证和反思

同样,本文提供了一个更为深入的细分,我鼓励您阅读

我还发现,与安德斯·海尔斯伯格的对话可能也很有趣。为了总结Anders Hejlsberg的观点,他补充说:Java泛型是为了最大限度地与现有JVM兼容而设计的,与C#中的实现相比,这导致了一些奇怪的事情:

  • 类型擦除强制实现将每个通用参数化值表示为
    对象
    。虽然编译器在
    对象
    和更具体的类型之间提供自动强制转换,但它不能消除类型强制转换和装箱对性能的负面影响
    (例如,
    Object
    被强制转换为特定类型
    MyClass
    int
    必须被放入
    Integer
    中,如果C#/.NET由于用户定义的值类型而采用类型擦除方法,这对C#/.NET来说会更加严重)。正如Anders所说:“你没有任何执行效率。”(具体化的泛型在C#中启用)

  • 类型擦除使编译时可用的信息在运行时不可访问。以前是
    List
    的东西变成了
    List
    ,无法在运行时恢复泛型类型参数。这使得围绕Java gene构建反射或动态代码生成场景变得困难rics。最近的一个例子是通过匿名类来解决这个问题。但是如果没有技巧,像通过反射在运行时生成代码这样的东西,从一个集合实例获取元素并将其放到另一个集合实例,在执行动态生成的代码时可能会在运行时失败:反射无助于捕获mi在这些情况下,
    列表
    列表
    匹配


但是+1是连接到Jonathan Pryor的答案。

我已经阅读了你的Strelok链接、Anders Hejlsberg链接和Eric Lippert链接。但我仍然无法理解-C#不进行类型擦除和引用类型如何共享相同的IL代码?你能对此进行一点扩展吗?@Alexander Malakhov所有引用类型在汇编中都是一个字大小,b可以吗e使用相同的指令进行操作,因此它们可以共享相同的汇编模式。你认为它们会有什么不同?我猜Java做的事情完全相同。那么,类型信息在哪里?例如,反射如何工作?@AlexanderMalakhov每个实例化仍然有一个唯一的类型对象,只是方法插槽都指向它同样的实现。java 10没有这样的计划。想知道它的性能有多高!@Tom“免于分析”是什么意思?这意味着,是的,你可以说“.NET泛型比java泛型好”.Java应该采取这种方法,做一个突破性的更改,并在有机会这样做的时候正确地实现泛型。“向后兼容”是不正确的,它们都是向后兼容的。这是为了“迁移兼容性”。@kervin希望您能详细说明。综合比较,带有一些链接。外观