当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《C++和Java中"泛型"类型之间有什么区别?》经验,为你挑选了6个好方法。

Java有泛型,C++提供了一个非常强大的编程模型template.那么,C++和Java泛型有什么区别?



1> Alexandru Ne..:

他们之间有很大的不同.在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的泛型当然有助于类型安全.


是的,直到最后一句话都很好的答案.
我认为*语法糖*很有用.
这不是纯粹的语法糖.编译器使用此信息来检查类型.即使信息在运行时不可用,我也不会将编译后使用的东西称为"语法糖".如果你这么称呼它,那么C就是汇编的语法糖,而这只是机器代码的语法糖:)
他是完全正确的,它只是一个复杂的语法糖.
你错过了一个主要的不同点,你可以使用什么来实例化泛型.在c ++中,可以使用template 并为用于实例化它的任何数字获得不​​同的结果.它用于编译时元编程.像答案:http://stackoverflow.com/questions/189172/c-templates-turing-complete
你不必'以'extends`或`super`的形式'指定一个类型'.答案不正确,
@EJP:你说的是,泛型不要求你指定一个子类或超类.但是在这个泛型类型的对象上调用方法的特定示例中,泛型类型必须具有声明此方法的超类(或接口).

2> cletus..:

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

  public String getPhoneNumber(String name) {
    return phoneNumbers.get(name);
  }

  ...
}

这就是所有Java Generics都是:用于投射对象的包装器.那是因为Java Generics没有改进.他们使用类型擦除.之所以做出这个决定,是因为Java Generics在这篇文章中出现这么晚,他们不想破坏向后兼容性(Map无论什么时候需要Map它都可以使用).与此相比,净/ C#在不使用类型擦除,从而导致各种各样的差异(例如,你可以使用基本类型和IEnumerableIEnumerable不承担任何关于彼此).

使用Java 5+编译器编译的泛型的类可用于JDK 1.4(假设它不使用任何其他需要Java 5+的功能或类).

这就是Java Generics被称为语法糖的原因.

但是这个关于如何做泛型的决定已经产生了深远的影响,以至于(精湛的)Java Generics FAQ如雨后春笋般出现,回答了人们对Java Generics提出的许多问题.

C++模板具有Java Generics不具备的许多功能:

使用原始类型参数.

例如:

template
class Matrix {
  int T[i][i];
  ...
}

Java不允许在泛型中使用原始类型参数.

使用默认类型参数,这是我在Java中遗漏的一个功能,但是存在向后兼容性原因;

Java允许绑定参数.

例如:

public class ObservableList {
  ...
}

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

除了与泛型的差异外,为了完整性,这里是C++和Java(以及另一个)的基本比较.

我也可以建议用Java思考.作为一名C++程序员,许多像对象这样的概念已经是第二天性,但是存在细微差别,所以即使你浏览部分内容也可以有一个介绍性文本.

学习Java时学到的很多东西都是库(都是标准的 - JDK中的内容 - 和非标准的,包括常用的东西,如Spring).Java语法比C++语法更冗长,并且没有很多C++特性(例如运算符重载,多重继承,析构机制等),但这并不严格地使它成为C++的子集.


需要注意的是,类型擦除问题不仅仅意味着"Map map = new HashMap "的向后兼容性.这意味着您可以在旧JVM上部署新代码,并且由于字节码的相似性,它将运行.
模板代码与复制粘贴*非常不同.如果从宏观扩展的角度考虑,迟早会遇到像这样的微妙错误:http://womble.decadentplace.org.uk/c++/template-faq.html#type-syntax-error

3> Shog9..:

C++有模板.Java有泛型,看起来有点像C++模板,但它们非常非常不同.

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

正如我所理解的那样,泛型工作方式相反:编译器使用类型参数来验证使用它们的代码是否类型安全,但生成的代码根本没有类型生成.

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

 


这是一个非常好的,简洁的解释.我想要做的一个调整是Java泛型是一个自动生成类型转换*的工具,保证安全*(在某些条件下).在某些方面,它们与C++的`const`有关.C++中的对象不会通过`const`指针修改,除非`const`-ness被逐出.同样,由Java中的泛型类型创建的隐式强制转换保证是"安全的",除非在代码中的某处手动地转换类型参数.

4> KeithB..:

C++模板具有Java泛型不具备的另一个特性是专业化.这允许您对特定类型具有不同的实现.例如,您可以为int提供高度优化的版本,同时仍然具有其他类型的通用版本.或者,您可以为指针和非指针类型使用不同的版本.如果你想在移动指针时操作解除引用的对象,这会派上用场.



5> Julien Chast..:

Java Generics和Collections中有一个很好的解释, 由Maurice Naftalin,Philip Wadler撰写.我强烈推荐这本书.报价:

Java中的泛型类似于C++中的模板....语法故意类似,语义故意不同....从语义上讲,Java泛型是由擦除定义的,其中C++模板是通过扩展定义的.

请在此处阅读完整说明.

替代文字
(来源:oreilly.com)



6> OscarRyz..:

基本上,AFAIK,C ++模板为每种类型创建代码副本,而Java泛型使用完全相同的代码。

是的,您可以说 C ++模板等效于Java泛型概念(尽管更恰当的说法是Java泛型在概念上等效于C ++)

如果您熟悉C ++的模板机制,您可能会认为泛型是相似的,但是相似性是肤浅的。泛型不会为每个专业生成新的类,也不允许“模板元编程”。

来自:Java泛型

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有