我主要使用Java,泛型相对较新。我一直读到Java做出了错误的决定,或者。net有更好的实现等等。
那么,c++, c#, Java在泛型上的主要区别是什么?利弊各有哪些?
我主要使用Java,泛型相对较新。我一直读到Java做出了错误的决定,或者。net有更好的实现等等。
那么,c++, c#, Java在泛型上的主要区别是什么?利弊各有哪些?
当前回答
看起来,在其他非常有趣的建议中,有一个是关于改进泛型和打破向后兼容性的:
Currently, generics are implemented using erasure, which means that the generic type information is not available at runtime, which makes some kind of code hard to write. Generics were implemented this way to support backwards compatibility with older non-generic code. Reified generics would make the generic type information available at runtime, which would break legacy non-generic code. However, Neal Gafter has proposed making types reifiable only if specified, so as to not break backward compatibility.
Alex Miller关于Java 7提案的文章
其他回答
c++很少使用“泛型”术语。相反,使用“模板”这个词更准确。模板描述了实现通用设计的一种技术。
c++模板与c#和Java实现的模板非常不同,主要有两个原因。第一个原因是c++模板不仅允许编译时类型参数,还允许编译时常量值参数:模板可以作为整数甚至函数签名。这意味着你可以在编译时做一些非常奇怪的事情,例如计算:
template <unsigned int N>
struct product {
static unsigned int const VALUE = N * product<N - 1>::VALUE;
};
template <>
struct product<1> {
static unsigned int const VALUE = 1;
};
// Usage:
unsigned int const p5 = product<5>::VALUE;
这段代码还使用了c++模板的另一个显著特性,即模板专门化。代码定义了一个类模板,product,它有一个值参数。它还为该模板定义了一个特化,每当参数的值为1时就使用该特化。这允许我在模板定义上定义递归。我相信这是安德烈·亚历山德雷斯库最先发现的。
模板专门化对于c++很重要,因为它允许数据结构的结构差异。模板作为一个整体是一种跨类型统一接口的方法。然而,尽管这是可取的,但在实现中不能平等对待所有类型。c++模板考虑到了这一点。这与OOP在覆盖虚方法的接口和实现之间的区别非常相似。
c++模板对于它的算法编程范型是必不可少的。例如,几乎所有容器的算法都定义为接受容器类型为模板类型并统一对待它们的函数。实际上,这并不完全正确:c++并不适用于容器,而是适用于由两个迭代器定义的范围,它们分别指向容器的开始部分和结束部分。因此,整个内容都由迭代器限定:begin <= elements < end。
使用迭代器而不是容器是有用的,因为它允许对容器的部分而不是整个进行操作。
c++的另一个显著特征是类模板的部分专门化。这在某种程度上与Haskell和其他函数式语言中参数的模式匹配有关。例如,让我们考虑一个存储元素的类:
template <typename T>
class Store { … }; // (1)
这适用于任何元素类型。但是我们假设,通过应用一些特殊的技巧,我们可以比其他类型更有效地存储指针。我们可以通过部分专门化所有指针类型来做到这一点:
template <typename T>
class Store<T*> { … }; // (2)
现在,每当我们为一种类型实例化容器模板时,都会使用适当的定义:
Store<int> x; // Uses (1)
Store<int*> y; // Uses (2)
Store<string**> z; // Uses (2), with T = string*.
c++模板实际上比c#和Java模板强大得多,因为它们在编译时进行计算,并支持专门化。这允许模板元编程,并使c++编译器等价于图灵机(即在编译过程中,你可以计算任何可以用图灵机计算的东西)。
注:我没有足够的观点来评论,所以请随意将此作为评论移动到适当的答案。
Contrary to popular believe, which I never understand where it came from, .net implemented true generics without breaking backward compatibility, and they spent explicit effort for that. You don't have to change your non-generic .net 1.0 code into generics just to be used in .net 2.0. Both the generic and non-generic lists are still available in .Net framework 2.0 even until 4.0, exactly for nothing else but backward compatibility reason. Therefore old codes that still used non-generic ArrayList will still work, and use the same ArrayList class as before. Backward code compatibility is always maintained since 1.0 till now... So even in .net 4.0, you still have to option to use any non-generics class from 1.0 BCL if you choose to do so.
所以我不认为java必须打破向后兼容性来支持真正的泛型。
维基百科上有很多比较Java/ c#泛型和Java泛型/ c++模板的文章。关于泛型的主要文章似乎有点混乱,但它确实有一些很好的信息。
Anders Hejlsberg自己在这里描述了“c#、Java和c++中的泛型”的区别。