我的问题:
为什么原始数据类型的大小是固定的?
集合如何动态增长?
假设原始数据类型还包含动态增长的特征或能力。然后,我们可以将数据类型从8减少到大约4,如“整数”,对于Float,Double组的所有Integer,Float,Short,Long和 float 组。为什么他们的结构不是这样的?
任何答案都将是完整的。提前谢谢。
答案 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)
原始数据类型是更复杂类型的构建块。最终,每种类型都由许多原始类型和/或数组组成。
原语修复的原因是:
int
类型的范围 - 无论它运行在哪台机器上。 (看看c,在这方面存在混淆)。