18

我已经阅读了C# 和 Java 的比较,列表中的第一件事是“单根(统一)类型系统”。

你能描述一下单根(统一)类型系统的含义吗?

4

2 回答 2

32

C# 有一个统一的类型系统。所有 C# 类型(包括 int 和 double 等原始类型)都继承自单个根object类型。与类对象不同,这些原始类型是值类型。它们不是单独在堆上分配的,而是按值传递的。

当 C# 值类型(例如原始 int 或用户定义的结构)放置在参数集合中时,它存储在没有指针的密集数组中。这是可能的,因为 C# 为所需的每个不同参数“大小”进行了自定义参数实例化。这意味着当您实例化 C#List<int>时,底层数组列表存储密集的 int 数组。

来源:http ://www.pin5i.com/showtopic-24376.html

Java有几种基本类型(int、long、double、byte 等)——然而,它们的特殊之处在于它们不是面向对象的,并且它们不能使用语言本身来定义。它们是值类型,不是堆分配的,而是按值传递的。

资料来源:C# 和 Java 的比较 - 统一类型系统(维基百科)

同时,Java 也有面向对象的原始“包装器”类型(Integer、Long、Double、Byte 等),通常称为boxed类型。这些是通过引用传递的堆分配对象,并且与上述原始类型并行存在。

在更新的 Java 版本中,基本类型会在必要时自动装箱为对象类型。这减轻了管理它们的大部分负担,但也可能导致细微的错误(另请参见自动装箱)。

与 C# 相比,在 Java 中,内置的 JDK Collections 框架始终管理对象指针的集合。为了使它们以向后兼容的方式参数化,Java 执行了一种称为类型擦除的技术,其中(在运行时)所有内容都被视为容器内的对象(在编译时执行参数化类型检查)。

这意味着您不能制作 Java List<int>,您只能制作List<Integer>. 而且,上面的列表实际上存储了一个指向装箱对象的指针数组Integer,它的大小是 C# 版本的两倍,性能也大大降低。对于大多数用例来说,这种大小和性能的差异是无关紧要的。

在大小和性能相关的用例中,有两个选项可用:

  1. 如果您事先知道列表的大小,请使用原生类型数组,例如int[]. 本机类型的数组被打包在内存中,因此它们消耗的内存更少并且性能更高。
  2. 如果您事先不知道列表的大小,请使用一些包装原生数组的 3rd 方列表实现,以便在创建后向其添加元素(一些示例:TroveColtFastutilGuava)。
于 2010-11-20T14:15:25.327 回答
12

这实际上也不适用于 C#,并非所有类型都派生自对象,就像其中 99.9% 一样。有几个非常奇怪的类型不能变成对象。唯一官方支持的是指针。还有 3 个不受支持,例如 TypedReference、RuntimeArgumentHandle 和第三个,它的名字让我无法理解。这 3 种类型与 C++/C 中具有可变长度方法的互操作一起使用。我不会太担心他们。

于 2010-11-20T19:22:27.470 回答