当前位置: 首页 > 面试题库 >

C#和Java…中的泛型与C ++中的模板之间有什么区别?

卢德惠
2023-03-14
问题内容

我主要使用Java,泛型相对较新。我一直在阅读Java做出了错误的决定,或者.NET具有更好的实现等。

那么,C ++,C#,Java在泛型之间的主要区别是什么?每个优点/缺点?


问题答案:

我将把声音添加到噪音中,并努力使事情变得清晰:

C#泛型允许你声明这样的内容。

List<Person> foo = new List<Person>();

然后编译器将阻止你将不在Person列表中的内容放入列表中。
在后台,C#编译器只是将其List<Person>放入.NET dll文件中,但是在运行时,JIT编译器会继续构建新的代码集,就好像你已经编写了一个用于容纳人员的特殊列表类一样- ListOfPerson

这样做的好处是它使速度变得非常快。没有任何强制转换或其他任何东西,并且由于dll包含这是List的信息,Person以后在使用反射查看它的其他代码可以告诉它包含Person对象(因此你得到了intellisense等)。

缺点是旧的C#1.0和1.1代码(在添加泛型之前)不理解这些新内容List<something>,因此你必须手动将其转换回普通的旧内容List才能与它们进行互操作。这并不是什么大问题,因为C#2.0二进制代码不向后兼容。唯一会发生的情况是,如果要将某些旧的C#1.0 / 1.1代码升级到C#2.0

Java泛型允许你声明这样的内容。

ArrayList<Person> foo = new ArrayList<Person>();

从表面上看,它看起来是一样的。编译器还会阻止你将不在Person列表中的内容放入列表中。

不同之处在于幕后发生的事情。与C#不同,Java并没有构建特殊的东西ListOfPerson-它只使用ArrayListJava中一直存在的普通样式。当你从阵列中取出东西时,Person p = (Person)foo.get(1);仍然必须执行通常的投射舞蹈。编译器可以节省你的按键操作,但仍然像以前一样,仍然会导致快速命中/广播。
当人们提到“类型删除”时,这就是他们在谈论的内容。编译器会为你插入强制类型转换,然后“擦除”以下事实:它Person不仅是列表Object

这种方法的好处是不需要理解泛型的旧代码就不必在意了。它仍然ArrayList像以前一样处理旧的问题。这在Java世界中更为重要,因为他们希望使用带有泛型的Java 5支持编译代码,并使其在旧版1.4或以前的JVM上运行,Microsoft故意决定不使用它。

缺点是我前面提到的速度降低,也是因为没有ListOfPerson伪类或类似的东西进入.class文件,以后会对其进行查看的代码(带有反射,或者如果你将其拉出另一个集合)它在什么地方被转换为Object等等)无法以任何方式告诉它是仅包含Person而不是仅包含任何其他数组列表的列表。

C ++模板允许你声明这样的内容

std::list<Person>* foo = new std::list<Person>();

它看起来像C#和Java泛型,并且会按你认为的方式工作,但是在幕后发生了许多事情。

它与C#泛型的最共同之处在于,它建立特殊的结构,pseudo-classes而不仅仅是像Java一样扔掉类型信息,但这是一条完全不同的鱼。

C#和Java都产生针对虚拟机设计的输出。如果你编写其中包含Person类的某些代码,则在两种情况下,有关Person类的某些信息都将放入.dll.class文件中,并且JVM / CLR将对此进行处理。

C ++生成原始的x86二进制代码。一切都不是对象,也没有底层虚拟机需要了解Person类。没有装箱或拆箱,功能不必属于类,甚至不属于任何东西。

因此,C ++编译器对模板的使用没有任何限制-基本上可以手动编写的任何代码,都可以为你编写模板。
最明显的示例是添加内容:

在C#和Java中,泛型系统需要知道可用于类的方法,并将其传递给虚拟机。告诉它的唯一方法是通过对实际的类进行硬编码或使用接口。例如:

string addNames<T>( T first, T second ) { return first.Name() + second.Name(); }

该代码不会在C#或Java中编译,因为它不知道该类型T实际上提供了一个称为Name()的方法。你必须告诉它-在C#中是这样的:

interface IHasName{ string Name(); };
string addNames<T>( T first, T second ) where T : IHasName { .... }

然后,你必须确保传递给addNames的东西实现IHasName接口,依此类推。Java语法不同( ),但存在相同的问题。

此问题的“经典”情况是试图编写一个执行此操作的函数

string addNames<T>( T first, T second ) { return first + second; }

你实际上无法编写此代码,因为无法使用其中的+方法声明接口。你失败了。

C ++不会遇到这些问题。编译器不在乎将类型传递给任何VM-如果两个对象都具有.Name()函数,它将进行编译。如果他们不这样做,那就不会。简单。



 类似资料:
  • 问题内容: Java具有泛型,而通过提供了非常强大的编程模型。那么,和Java泛型之间有什么区别? 问题答案: 它们之间有很大的区别。在C ++中,您不必为泛型类型指定类或接口。这就是为什么您可以创建真正的泛型函数和类,而不必担心键入错误。 上面的方法添加了两个相同类型的对象,并且可以用于具有“ +”运算符的任何类型T。 在Java中,如果要在传递的对象上调用方法,则必须指定一种类型,例如: 在C

  • 问题内容: 我从这里阅读了一篇有趣的文章/主题/讨论,并且遇到了以下问题: Java / C#泛型的局限性是什么? C ++模板有什么功能,而Java / C#泛型则没有呢? 编辑1 Eric Lippert推荐的其他问题 C#泛型可能有哪些模式,而C ++模板却没有? C#的真实泛型类型和Java的类型擦除泛型类型之间有什么区别? 问题答案: 首先,您可能想阅读我在2009年关于该主题的文章。

  • 问题内容: 我正在使用Eclipse来帮助我清理一些代码以正确使用Java泛型。大多数时候,它在推断类型方面做得非常出色,但是在某些情况下,推断类型必须尽可能地通用:对象。但是Eclipse似乎给了我一个选择,可以选择对象类型还是“?”类型。 那么两者之间有什么区别? 和 问题答案: 匹配项的实例,但不是。假设您要编写一个接受Strings到任何内容的映射的方法:如果您要编写 您无法提供。如果你写

  • 问题内容: C ++或Java中的类型转换和类型转换之间有什么区别? 问题答案: 类型 转换 将变量引用的值(内存块)视为与声明该变量的类型不同的类型。 类型 转换 实际上是在对该值进行转换。 在许多语言中, 某些 强制转换(通常是数字强制转换)的确会导致转换(这会因语言而异),但大多数情况下只是“将X当作Y处理”。 像人类语言的大多数方面一样,不幸的是,这些术语在不同社区中的使用略有不同,主要是

  • C# 最吸引人的地方是它与 Java 的区别而不是它们之间的相似性。下面就来介绍一下 C# 与 Java 之间的区别: 序号 Java C# 1 Java 是 Oracle 开发的一种高级、健壮、安全和面向对象的编程语言 C# 是微软开发的在 .Net Framework 上运行的一种面向对象的编程语言 2 Java 语言需要在 Java 运行环境(JRE)下运行  C# 语言需要在公共语言运行库

  • 问题内容: 这两个关键字具有完全相同的效果,还是我应该注意一些事情? 问题答案: 根据此站点的资料:[http]( http://en.csharp- online.net/CSharp_FAQ:_What_is_the_difference_between_CSharp_lock_and_Java_synchronized) //en.csharp-online.net/CSharp_FAQ :