为什么原始数据类型是用它们的内存修复的?

时间:2014-03-06 11:57:30

标签: java

我的问题:

  • 为什么原始数据类型的大小是固定的?

  • 集合如何动态增长?

假设原始数据类型还包含动态增长的特征或能力。然后,我们可以将数据类型从8减少到大约4,如“整数”,对于Float,Double组的所有Integer,Float,Short,Long和 float 组。为什么他们的结构不是这样的?

任何答案都将是完整的。提前谢谢。

2 个答案:

答案 0 :(得分:3)

硬件基元始终具有已定义的大小,否则您将难以处理内存布局,将字节转换为基元,反之亦然等。软件基元(由语言提供的内置数据类型)可能不需要是固定大小但这会使内存操作和数据传输更加复杂。

例如,如果您要从文件中读取整数,您会读取多少字节? 1,2,4,8?

在内存中你会遇到类似的问题:如果一个对象由两个短整数组成,即2x2字节,如果第一个整数需要增长甚至移动整个对象,你需要移动第二个整数。这将是一个性能损失,只有只有一个整数类型才能得到补偿。


另一方面,集合可以增长,因为它们可以引用堆的不同部分,或者如果需要更多空间,则将它们的内容复制到堆的更大部分。

ArrayList为例。在内部,它使用一个位于连续内存块中的数组(否则通过使用数组的地址来访问内存,并且元素的索引不起作用)并且如果该数组需要增长,则更大的数组是创建并将原始数组复制到新数组。

另一方面,

LinkedList分布在堆上,因为每个条目只包含对前一个和下一个条目以及元素的引用。这使得列表变得更容易,但是访问某个元素会要求您搜索所有元素,直到找到您感兴趣的元素。

另一个例子:

取一组int值:1,2,3,4,5,6

数组列表(请注意,JDK不提供基本列表,但还有其他库可以存储),如下所示(十六进制值,与此示例无关的字节顺序):

//Those are hex bytes
|--- 1 ---| |--- 2 ---| |--- 3 ---| |--- 4 ---| |--- 5 ---| |--- 6 ---|
00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06

现在,如果要访问元素4(索引3),您只需要知道第一个元素的内存地址,并添加index * 4个字节以获取第4个元素的位置。然后读取接下来的4个字节,你就有了元素值。 (4个字节,因为int被定义为32位,即4个字节)。

如果没有这些信息,你必须采取更多行动来获得第4个元素。

现在考虑一个链表

Element 0 <-> Element 1 <-> Element 2 <-> Element 3 <-> Element 4 <-> Element 5
  |             |             |             |             |             |
  v             v             v             v             v             v              
Value 1       Value 2       Value 3       Value 4       Value 5       Value 6

在内存中,元素可能会像这样布局:

 Element 5, other stuff, Element 3, Element 4, other stuff, Element 0, Element 2, Element 1

正如您所看到的,元素可以在内存中任何地方,因此您不能仅通过使用内存地址,索引和元素大小来访问第4个元素。相反,你必须从元素0开始,找到元素1然后是2等,直到你找到了你正在寻找的元素。

答案 1 :(得分:1)

原始数据类型是更复杂类型的构建块。最终,每种类型都由许多原始类型和/或数组组成。

原语修复的原因是:

  1. 它们应该与当代计算机支持的原始类型相匹配。例如,IEEE双值。
  2. 为了方便携带。例如,在java中,您知道int类型的范围 - 无论它运行在哪台机器上。 (看看c,在这方面存在混淆)。