为了账号安全,请及时绑定邮箱和手机立即绑定

C ++和Java中的“泛型”类型之间有什么区别?

C ++和Java中的“泛型”类型之间有什么区别?

慕少森 2020-02-04 14:27:02
Java具有泛型,而C ++通过templates 提供了非常强大的编程模型。那么,C ++和Java泛型有什么区别?
查看完整描述

4 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

它们之间有很大的区别。在C ++中,您不必为泛型类型指定类或接口。这就是为什么您可以创建真正的泛型函数和类,而不必担心键入错误。


template <typename T> T sum(T a, T b) { return a + b; }

上面的方法添加了两个相同类型的对象,并且可以用于具有“ +”运算符的任何类型T。


在Java中,如果要在传递的对象上调用方法,则必须指定一种类型,例如:


<T extends Something> 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的泛型当然有助于类型安全。


查看完整回答
反对 回复 2020-02-04
?
慕运维8079593

TA贡献1876条经验 获得超5个赞

Java泛型是大量 C ++模板不同。


基本上,在C ++中,模板基本上是经过修饰的预处理器/宏集(注意:由于某些人似乎无法理解类推,因此我并不是说模板处理是宏)。在Java中,它们基本上是语法糖,可最大程度地减少对象的样板转换。这是对C ++模板与Java泛型的相当不错的介绍。


要详细说明这一点:使用C ++模板时,基本上是在创建代码的另一个副本,就像使用#define宏一样。这使您可以执行一些操作,例如int在模板定义中使用参数来确定数组的大小等。


Java不能那样工作。在Java中,所有对象都来自java.lang.Object,因此,泛型之前,您需要编写如下代码:


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 Map<String, String> phoneNumbers = new HashMap<String, String>();


  public String getPhoneNumber(String name) {

    return phoneNumbers.get(name);

  }


  ...

}

这就是Java泛型的全部内容:转换对象的包装器。那是因为Java泛型没有改进。他们使用类型擦除。之所以做出此决定,是因为Java泛型出现的太晚了,以至于他们不想破坏向后兼容性(Map<String, String>只要需要a,就可以使用a Map)。将此与未使用类型擦除的.Net / C#进行比较,这会导致各种差异(例如,您可以使用原始类型,IEnumerable并且IEnumerable<T>彼此之间没有任何关系)。


在JDK 1.4上可以使用使用Java 5+编译器编译的泛型的类(假定它不使用任何其他需要Java 5+的功能或类)。


这就是Java泛型被称为语法糖的原因。


但是,关于如何执行泛型的决定产生了深远的影响,以至于(一流的)Java Generics FAQ迅速出现,回答了人们对Java Generics的许多问题。


C ++模板具有Java泛型所没有的许多功能:


使用原始类型参数。


例如:


template<class T, int i>

class Matrix {

  int T[i][i];

  ...

}

Java不允许在泛型中使用基本类型参数。


使用默认类型参数,这是我在Java中缺少的功能之一,但是有向后兼容性的原因;


Java允许参数的边界。

例如:


public class ObservableList<T extends List> {

  ...

}

确实需要强调的是,具有不同参数的模板调用实际上是不同的类型。他们甚至不共享静态成员。在Java中并非如此。


除了与泛型的区别之外,出于完整性的考虑,这里是C ++和Java(以及另一个)的基本比较。


我也可以建议使用Java进行思考。作为C ++程序员,对象之类的许多概念已经是天生的,但是存在细微的差异,因此即使您略过部分内容,也应该有介绍性的文本。


学习Java时,您会学到的很多东西都是库(标准库(JDK中附带的库)和非标准库(包括诸如Spring之类的常用东西)。Java语法比C ++语法更冗长,并且不具有许多C ++功能(例如,运算符重载,多重继承,析构函数等),但这也并非严格使其成为C ++的子集。


查看完整回答
反对 回复 2020-02-04
?
繁华开满天机

TA贡献1816条经验 获得超4个赞

C ++具有模板。Java具有泛型,看上去有点像C ++模板,但是它们非常非常不同。


顾名思义,模板通过为编译器提供一个(正在等待...)模板来工作,模板可以通过填充模板参数来生成类型安全代码。


据我所知,泛型的工作方式相反:编译器使用类型参数来验证使用它们的代码是否是类型安全的,但是生成的代码根本没有类型。


将C ++模板视为一个非常好的宏系统,将Java泛型视为自动生成类型转换的工具。


查看完整回答
反对 回复 2020-02-04
?
喵喵时光机

TA贡献1846条经验 获得超7个赞

C ++模板具有Java泛型所没有的另一个功能是专业化。这使您可以对特定类型使用不同的实现。因此,例如,您可以为int拥有高度优化的版本,而对于其余类型仍然具有通用版本。或者,您可以为指针和非指针类型使用不同的版本。如果要在传递指针时对取消引用的对象进行操作,这将很方便。


查看完整回答
反对 回复 2020-02-04
  • 4 回答
  • 0 关注
  • 867 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信