前几天我正在阅读Kernighan和Rob Pike的编程实践。
在第二章中,在搜索部分下,我读到了一些在我脑海中造成混淆的行。
"没有什么比用于存储静态表格数据的数组更好。编译时初始化 使得构造这样的数组变得便宜和容易。 (在Java中,初始化发生在 运行时,但这是一个不重要的实现细节,除非数组很大。)"
我的问题是,如果用户只在运行时提供数组或变量的编译时初始化,并且变量的内存分配在运行时发生,那么在任何语言中如何都可以进行编译时初始化。不知道内存地址如何初始化数组?
答案 0 :(得分:1)
它没有说数据是在运行时提供的。它只是说“静态”数据。如果在编译时已知,则编译器可以将其编译到代码中。 API密钥,带有“幻数”的表或错误消息文本符合该模式。
答案 1 :(得分:1)
我认为你误解了作者所说的话。注意:
这是一个静态数组,在Java中:
String[] suit = {
"item 1",
"item 2",
"item 3",
"item 4"
};
现在,Java不允许您声明真正的动态数组,如Delphi和其他语言,对于动态数组,我们必须选择另一个名为ArrayList
的数据结构,如下例所示:< / p>
List<String> list = new ArrayList<String>();
如果用户想要使用具有运行时定义长度的静态数组,他可以做的最灵活的方法如下:
int maxsize = Integer.ParseInt(JOP.ShowInputDialog("give me a number")...);
int[] myArray = new int[maxsize]();
这是Delphi中的静态数组:
const MyStaticArray : array [0..3] of Integer = (0, 1, 2, 3);
这是动态数组
var MyDinamicArray : array of Integer;
MaxSize: Integer;
begin
MaxSize := StrToInt(InputBox(..,'Give me a number', ..));
SetLength(MyDinamicArray, MaxSize); //Defines the array size, in runtime;
end;
我的问题是,如何使用任何语言进行编译 如果用户要去的话,数组或变量的时间初始化 仅在运行时提供它以及为内存分配 变量在运行时发生。不知道内存地址 如何初始化数组?
也就是说,我们可以很容易地看到,这是一个“编译时”初始化(与实现细节无关)
String[] suit = {
"item 1",
"item 2",
"item 3",
"item 4"
};
一旦阵列初始化,不能调整大小,因此操作系统可以在任何需要的地方分配内存。由于数组在内存中是顺序,因此通过使用索引,Java知道您想要获取的地址。
考虑上面的数组,这是内存草图:
//程序存储器
address 00A1
value | 00BA |
alias suit
// OS Memory
address 00BA 00BB 00BC 00BD
value | "item 1" | "item 2" | "item 3" | "item 4" |
alias suit[0] suit[1] suit[2] suit[3]
这里的字符串使得它易于理解,实际上String也是指向某事物的指针。
别名是Java隐藏指针算法的方式,即允许我们访问索引而不是内存地址。
以下是有关数组的一些文档:
答案 2 :(得分:0)
来自JLS
数组类型的变量包含对象的引用。 声明一个 数组类型的变量不会创建数组对象或分配任何数组 数组组件的空间。它只创建变量本身 可以包含对数组的引用。
然而,声明者的初始化部分(§8.3,§9.3,§14.4.1) 可以创建一个数组,一个引用然后成为初始数组 变量的值。