为什么有人声称Java的泛型实现很糟糕?

问题

我偶尔听说过,通用泛型,Java并没有把它弄好。 (最近的参考,here)

原谅我的经验不足,但是什么会让他们变得更好?


#1 热门回答(129 赞)

坏:

  • 类型信息在编译时丢失,因此在执行时你无法确定它的"含义"类型
  • 不能用于值类型(这是一个大问题 - 在.NET中,List <byte>确实由byte []支持,例如,不需要装箱)
  • 调用泛型方法的语法很糟糕(IMO)
  • 约束的语法可能会令人困惑
  • 通配符通常令人困惑
  • 由于上述铸造等各种限制

好:

  • 通配符允许在呼叫方指定协方差/逆变,这在许多情况下非常简洁
  • 总比没有好!

#2 热门回答(25 赞)

最大的问题是Java泛型只是一个编译时的东西,你可以在运行时颠覆它。 C#受到称赞,因为它进行了更多的运行时检查。在this post中有一些非常好的讨论,它与其他讨论有关。


#3 热门回答(13 赞)

  • 运行时实现(即不是类型擦除);
  • 使用原始类型的能力(这与(1)有关);
  • 虽然通配符很有用,但语法和知道何时使用它会让很多人感到困惑。和
  • 没有性能提升(因为(1); Java泛型是铸造对象的语法糖)。

(1)导致一些非常奇怪的行为。我能想到的最好的例子是。承担:

public class MyClass<T> {
  T getStuff() { ... }
  List<String> getOtherStuff() { ... }
}

然后声明两个变量:

MyClass<T> m1 = ...
MyClass m2 = ...

现在致电getOtherStuff()

List<String> list1 = m1.getOtherStuff(); 
List<String> list2 = m2.getOtherStuff();

第二个是它的泛型类型参数被编译器剥离,因为它是一个原始类型(意味着没有提供参数化类型),即使它与参数化类型没有关系。

我还会提到我最喜欢的JDK声明:

public class Enum<T extends Enum<T>>

除了通配符(这是一个混合包)我只是认为.Net泛型更好。