C#vs Java泛型

时间:2008-12-10 04:12:29

标签: c# java generics comparison

我听说Generics的Java实现不如C#实现那么好。因为语法看起来很相似,它对于Java实现是不合标准的,还是一种宗教观点?

3 个答案:

答案 0 :(得分:156)

streloksi's link在分解差异方面做得很好。快速而肮脏的总结虽然是......

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

最大的不同之处在于实施。

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

另一方面,C#凭借CLR,实现了泛型,直到字节码。为了支持2.0中的泛型,CLR进行了几次重大更改。优势在于性能改进,深层安全验证和反思。

再次提供的link有更深入的细分我鼓励您阅读

答案 1 :(得分:33)

差异归结于微软和Sun的设计决策。

Generics in Java由编译器通过type erasure实现,这意味着在编译时进行类型检查,并删除类型信息。采用这种方法是为了使遗留代码与使用泛型的新代码保持兼容:

来自Java教程,Generics: Type Erasure

  

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

但是,对于generics in C# (.NET),编译器没有类型擦除,并且在运行时期间执行类型检查。这样做的好处是类型信息保存在已编译的代码中。

来自维基百科:

  

利用这种设计选择   提供其他功能,例如   允许反射   保留泛型类型   减轻了一些局限   擦除(例如无法擦除)   创建通用数组)。这个   也意味着没有   从运行时强制转换中获得的性能   通常是昂贵的拳击转换。

不应该说“.NET泛型优于Java泛型”,而应该研究实现泛型的方法的不同之处。在Java中,似乎保留兼容性是一个高优先级,而在.NET(在2.0版本中引入)时,实现使用泛型的全部好处是一个更高的优先级。

答案 2 :(得分:5)

还与Anders Hejlsberg进行了this对话,这可能也很有趣。总结一下Anders Hejlsberg提出的一些要点: Java泛型是为了与现有JVM的最大兼容性导致了一些奇怪的事情,而不是你在C#中看到的实现:

  • 键入擦除力实现,将每个通用参数化值表示为Object。虽然编译器提供Object和更具体类型之间的自动转换,但不会消除类型转换和装箱对性能的负面影响(例如Object转换为特定类型MyClassint必须在Integer中装箱,如果因为用户定义的值类型而遵循类型擦除方法,那么对于C#/ .NET来说则更为严重。正如Anders所说:“你没有获得任何执行效率”(在C#中使用了具体的泛型)

  • 类型擦除使编译时可用的信息在运行时无法访问。曾经是List<Integer>的东西变成了List,无法在运行时恢复泛型类型参数。 这使得围绕Java泛型构建反射或动态代码生成方案变得困难。更新近SO answer通过匿名类展示了解决方法。但是没有技巧,比如在运行时通过反射生成代码,从一个集合实例获取元素并将其放到另一个集合实例,在运行时可能会在执行动态生成的代码时失败:反射无助于捕获{{1}中的不匹配在这些情况下,与List<Double>对比。

但是链接+1给Jonathan Pryor blog post的答案。

豫ICP备18024241号-1