【发布时间】:2012-01-05 06:16:00
【问题描述】:
陪我一会儿。我知道这听起来有点主观和争论,但我发誓最后有一个问号,这个问题实际上可以客观地回答......
来自 .NET 和 C# 背景,近年来,我被泛型与扩展方法相结合在许多 .NET 常见问题的解决方案中提供的语法糖宠坏了。使 C# 泛型如此强大的关键特性之一是,如果其他地方有足够的信息,编译器可以推断类型参数,所以我几乎不需要写出它们。在您意识到您节省了多少击键之前,您不必编写很多代码行。例如,我可以写
var someStrings = new List<string>();
// fill the list with a couple of strings...
var asArray = someStrings.ToArray();
而 C# 只会知道我的意思是第一个 var 是 List<string>,第二个是 string[] 并且 .ToArray() 真的是 .ToArray<string>()。
那我来Java。
我对 Java 泛型了解得足够多,知道它们在本质上是不同的,除此之外,编译器实际上不会编译为泛型代码——它会剥离类型参数并生成它无论如何,以某种(相当复杂的)方式(我还没有真正理解)工作。但即使我知道 Java 中的泛型根本不同,我还是不明白为什么需要这样的构造:
ArrayList<String> someStrings = new ArrayList<String>();
// fill the list with a couple of strings...
String[] asArray = someStrings.toArray(new String[0]); // <-- HERE!
到底为什么我必须实例化一个新的String[],其中没有任何元素,不会用于任何事情,以便Java编译器知道它是String[]和不是我想要的任何其他类型的数组吗?
我意识到这就是重载的样子,而toArray() 当前返回的是Object[]。但是,为什么在发明 Java 的这一部分时会做出这个决定呢?为什么这种设计比完全跳过返回Object[]overload 的.toArray() 而只使用返回T[] 的toArray() 更好?这是编译器的限制,还是框架这部分设计者的想象,还是其他什么?
正如你可能从我对最不重要的事情的强烈兴趣中看出的那样,我有一段时间没睡了……
【问题讨论】:
-
stackoverflow.com/questions/520527/… 提供了很好的信息
-
由于 Java 7 提供了“钻石”运算符,这使得泛型的实例化稍微(实际上只是一点点)更舒服:
ArrayList<Integer> l = new ArrayList<>();。 -
@home:“钻石运算符”确实让事情变得更容易了。有点... ;) 但我仍然觉得它很...有趣... Java 要求我指定集合的类型 4 次,而 C# 只需要指定一次。如果我执行 C# 中不允许的操作(例如,尝试将字符串强制转换为整数),我仍然会遇到编译错误,但 编译器 会为我跟踪。如果我愿意,我也可以,但我不必。
-
@TomasLycken:C# 受益于能够从 Java 在此过程中犯下的许多错误中学习。如果 Java 放弃了向后兼容性,那么它也可以做很多 C# 做得好的事情。在 Java 中需要声明的数量非常可笑,但它是一种较旧的语言,其中包含许多新特性。
-
“从我对最不重要的事情的极度兴趣中你可能可以看出......”。这是邀请我们否决您的问题吗? :-)