代码之家  ›  专栏  ›  技术社区  ›  johnc

C.V.VS Java泛型[复制]

  •  109
  • johnc  · 技术社区  · 16 年前

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

    3 回复  |  直到 7 年前
        1
  •  149
  •   Ufuk Hacıoğulları    11 年前

    streloksi's link 在消除分歧方面做得很好。不过,快速而肮脏的总结是…

    在语法和用法方面。语言之间的语法大致相同。偶尔会有一些怪癖(尤其是在限制条件下)。但基本上,如果你能阅读其中一个,你就可以阅读/使用另一个。

    但最大的区别在于实现。

    Java使用类型擦除的概念来实现泛型。简而言之,底层编译类实际上不是通用类。它们编译成对象并强制转换。实际上,Java泛型是编译时工件,并且可以在运行时很容易地被颠覆。

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

    再次提供 link 有一个更深入的分解我鼓励你阅读

        2
  •  31
  •   coobird    16 年前

    区别在于微软和Sun的设计决策。

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

    从Java教程中, Generics: Type Erasure :

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

    然而,随着 generics in C# (.NET) ,编译器不清除类型,类型检查在运行时执行。这样做的好处是类型信息保存在编译后的代码中。

    维基百科:

    此设计选项可用于 提供其他功能,例如 允许反射 保存通用类型 减轻了一些限制 擦除(例如无法 创建泛型数组)。这个 也意味着没有 运行时强制转换和 通常是昂贵的拳击转换。

    与其说“.NET泛型比Java泛型好”,不如看一下实现泛型的方法的不同之处。在Java中,保持兼容性是一个很高的优先级,而在.NET中(当在版本2中介绍时),实现使用泛型的全部好处是一个更高的优先级。

        3
  •  5
  •   IgorK    7 年前

    还发现 this 与安德斯·海斯伯格的谈话可能也很有趣。为了总结安德斯·赫杰斯伯格(Anders Hejlsberg)在附加说明中提出的观点: Java泛型与现有JVM的最大兼容性 这与在C中看到的实现相比,导致了一些奇怪的事情:

    • 类型擦除强制实现将每个通用参数化值表示为 Object . 而编译器提供 对象 更具体的类型是 不会消除类型转换和装箱对性能的负面影响 (例如) 对象 强制转换为特定类型 MyClass int 必须装在箱子里 Integer ,如果由于用户定义的值类型而采用类型擦除方法,那么对于C/.NET来说,这将更为严重。正如安德斯所说:“你得不到任何执行效率”(C中的具体化泛型实现了这一点)。

    • 类型擦除使编译时的信息在运行时不可访问 . 曾经是 List<Integer> 变成一个 List 无法在运行时恢复泛型类型参数。 这很难在Java泛型周围建立反射或动态代码生成场景。 最近 SO answer 通过匿名类显示绕过它的方法。但是,如果没有技巧,例如通过反射在运行时生成代码,从而从一个集合实例获取元素并将其放入另一个集合实例,则在动态生成的代码执行期间,反射可能会在运行时失败:反射没有帮助捕获 List<Double> 对战 列表<integer> 在这种情况下。

    但是+1代表与乔纳森·普赖尔有关的答案 blog post .