Java有泛型,C++提供了一个非常强大的编程模型template
.那么,C++和Java泛型有什么区别?
他们之间有很大的不同.在C++中,您不必为泛型类型指定类或接口.这就是为什么你可以创建真正通用的函数和类,并注意更宽松的输入.
template T sum(T a, T b) { return a + b; }
上面的方法添加了两个相同类型的对象,并且可以用于任何具有"+"运算符的类型T.
在Java中,如果要在传递的对象上调用方法,则必须指定类型,如:
T sum(T a, T b) { return a.add ( b ); }
在C++中,通用函数/类只能在头文件中定义,因为编译器为不同的类型生成不同的函数(它被调用).因此编译速度较慢.在Java中,编译没有重大损失,但Java使用一种称为"擦除"的技术,其中泛型类型在运行时被擦除,因此在运行时Java实际上正在调用...
Something sum(Something a, Something b) { return a.add ( b ); }
所以Java中的泛型编程并不是真正有用,它只是帮助新的foreach构造的一点点语法糖.
编辑:上面关于有用性的观点是由年轻人自己写的.Java的泛型当然有助于类型安全.
Java泛型是大量 C++模板不同.
基本上在C++模板中基本上是一个美化的预处理器/宏集(注意:因为有些人似乎无法理解一个类比,我不是说模板处理是一个宏).在Java中,它们基本上是语法糖,以最小化对象的样板转换.这是对C++模板与Java泛型的相当不错的介绍.
要详细说明这一点:当您使用C++模板时,您基本上是在创建代码的另一个副本,就像使用#define
宏一样.这允许您执行诸如int
在模板定义中具有确定数组大小等的参数之类的事情.
Java不像那样工作.在Java中,所有对象都来自java.lang.Object,所以,在Generics之前,你要编写如下代码:
public class PhoneNumbers { private Map phoneNumbers = new HashMap(); public String getPhoneNumber(String name) { return (String)phoneNumbers.get(name); } ... }
因为所有Java集合类型都使用Object作为其基类型,因此您可以在其中放置任何内容.Java 5滚动并添加泛型,因此您可以执行以下操作:
public class PhoneNumbers { private MapphoneNumbers = new HashMap (); public String getPhoneNumber(String name) { return phoneNumbers.get(name); } ... }
这就是所有Java Generics都是:用于投射对象的包装器.那是因为Java Generics没有改进.他们使用类型擦除.之所以做出这个决定,是因为Java Generics在这篇文章中出现这么晚,他们不想破坏向后兼容性(Map
无论什么时候需要Map
它都可以使用).与此相比,净/ C#在不使用类型擦除,从而导致各种各样的差异(例如,你可以使用基本类型和IEnumerable
和IEnumerable
不承担任何关于彼此).
使用Java 5+编译器编译的泛型的类可用于JDK 1.4(假设它不使用任何其他需要Java 5+的功能或类).
这就是Java Generics被称为语法糖的原因.
但是这个关于如何做泛型的决定已经产生了深远的影响,以至于(精湛的)Java Generics FAQ如雨后春笋般出现,回答了人们对Java Generics提出的许多问题.
C++模板具有Java Generics不具备的许多功能:
使用原始类型参数.
例如:
templateclass Matrix { int T[i][i]; ... }
Java不允许在泛型中使用原始类型参数.
使用默认类型参数,这是我在Java中遗漏的一个功能,但是存在向后兼容性原因;
Java允许绑定参数.
例如:
public class ObservableList{ ... }
确实需要强调的是,具有不同参数的模板调用确实是不同的类型.他们甚至不共享静态成员.在Java中,情况并非如此.
除了与泛型的差异外,为了完整性,这里是C++和Java(以及另一个)的基本比较.
我也可以建议用Java思考.作为一名C++程序员,许多像对象这样的概念已经是第二天性,但是存在细微差别,所以即使你浏览部分内容也可以有一个介绍性文本.
学习Java时学到的很多东西都是库(都是标准的 - JDK中的内容 - 和非标准的,包括常用的东西,如Spring).Java语法比C++语法更冗长,并且没有很多C++特性(例如运算符重载,多重继承,析构机制等),但这并不严格地使它成为C++的子集.
C++有模板.Java有泛型,看起来有点像C++模板,但它们非常非常不同.
顾名思义,模板的工作原理是为编译器提供一个(等待它......)模板,它可以通过填充模板参数来生成类型安全的代码.
正如我所理解的那样,泛型工作方式相反:编译器使用类型参数来验证使用它们的代码是否类型安全,但生成的代码根本没有类型生成.
将C++模板视为一个非常好的宏系统,将Java泛型视为自动生成类型转换的工具.
C++模板具有Java泛型不具备的另一个特性是专业化.这允许您对特定类型具有不同的实现.例如,您可以为int提供高度优化的版本,同时仍然具有其他类型的通用版本.或者,您可以为指针和非指针类型使用不同的版本.如果你想在移动指针时操作解除引用的对象,这会派上用场.
Java Generics和Collections中有一个很好的解释, 由Maurice Naftalin,Philip Wadler撰写.我强烈推荐这本书.报价:
Java中的泛型类似于C++中的模板....语法故意类似,语义故意不同....从语义上讲,Java泛型是由擦除定义的,其中C++模板是通过扩展定义的.
请在此处阅读完整说明.
(来源:oreilly.com)
基本上,AFAIK,C ++模板为每种类型创建代码副本,而Java泛型使用完全相同的代码。
是的,您可以说 C ++模板等效于Java泛型概念(尽管更恰当的说法是Java泛型在概念上等效于C ++)
如果您熟悉C ++的模板机制,您可能会认为泛型是相似的,但是相似性是肤浅的。泛型不会为每个专业生成新的类,也不允许“模板元编程”。
来自:Java泛型