![f6502b797904a1db64a400efe9049d43.png](https://i-blog.csdnimg.cn/blog_migrate/c637887e7de5b0ffc196f8a430b7f7b5.jpeg)
标有“中级”和“高级”的级别指的是考试,而不是问题。尽管在几乎所有情况下,“高级”问题都会更难回答。我们为认证考试编写试题,我们打算采用同样的规则:以文字的表面价值为依据,相信这些试题并不是为了欺骗你,而是直接测试你对语言的内部和外部知识。
这个问题的目标是声明、实例化、初始化和使用一维数组。给定以下代码块:
int[] ia = new int[2];
ia[1] = 1;
for (int v : ia) System.out.print(v + " ");
String[] sa = new String[2];
sa[0] = "Hi";
for (String v : sa) System.out.print(v + " "); // line n1
What is the output?Choose one.(哪一个是输出请选择一个):
0 1 Hi null
null 1 Hi null
0 1 0 Hi null null
null 1 null Hi null null
0 1 Hi
, followed by an exception thrown at line n1
答案。这个问题研究数组的创建和初始化。在本例中,使用一维数组,但多维数组本质上只是数组的数组,多维数组也是考试目标的一部分。因此,虽然有些额外的细节与他们有关,但这一讨论基本上对他们也是正确的。
数组可以通过以下几种方式创建:可以使用带有关键字new或数组文本的构造函数表单。这个问题使用构造器表单,该表单要求在类型后面的方括号中提供数组的维度。此方法还阻止您同时指定要放入数组中的值。
文本格式使用大括号,在数组大小很小时特别优雅,它允许并且实际上要求您同时显式地初始化元素。
数组文字有两种语法形式。最普通的是这样的:
new int[] {1, 1}
如图所示,这种通用形式是“int数组”类型的表达式,它可以在任何需要该类型表达式的情况下使用。因此,例如,它可以在方法调用的实际参数列表中使用,如下所示:
doStuffWithIntArray(new int[] {1, 1});
或者是一个简单的任务,例如:
int[] ia;
ia = new int[] {1, 1};
也可以用于其他场合。
注意,在此表单中(与构造函数表单不同),方括号不包含数组维度;数组的大小是从初始化值列表中推断出来的。
第二种形式,也许更为熟悉,实际上是一种速记,只允许作为初始化变量声明的值部分。该表单只能在以下情况下使用:
int[] ia = { 1, 1 };
另一个注意事项是,在变量声明中,在变量名后面加上方括号是合法的。这种语法形式不太常见,因为大多数人喜欢声明左边的“type”部分和右边的“name”部分。然而,它是Java前驱体、C和C++中使用的形式,所以您可能会遇到它。那张表格看起来是这样的:
int ia[];
让我们回到问题上来,这个问题不使用这些文字形式。这两个数组都是使用构造函数表单创建的。因此,您没有机会将元素值指定为构造过程的一部分,并且您要表示的任何特定值都必须在之后指定。
当然,这个问题中的显式赋值并没有设置数组的所有值,而这个问题的关键是在没有显式赋值的数组元素中可以找到哪些值。
实际上,这个问题“默认值是多少?”“不仅仅适用于数组。在堆上分配的任何东西,包括所有的对象,不管它们是数组还是更明显的对象(这里的重点是数组在Java中是对象),都会受到与内存分配不可分割的默认初始化的影响。如果您在堆中请求一个新对象,JVM要么为您的代码显示默认的初始化内存,要么显示一个异常。您永远无法获取绕过此默认初始化的值。
默认初始化是什么?简单:它是零或类似于零的值。对于char数值类型和字符,它将为零;对于布尔值,它将为false;对于所有对象引用值,它将为null。
因此,new int[2]为一个具有两个原始int值的数组保留空间。它们的索引(也称为下标)将是0和1(Java的数组索引总是基于零),并且这两个元素的值都是0。因此,此时,您有ia[0]==0和ia[1]==0。
下一行将值1赋给第二个元素(当然下标是1),并将第一个元素保留为默认值0。
接下来,使用一个简单的循环来打印int数组中的值。您已经看到将有两个值:0和1。因此,这部分代码的输出将是0 1(注意,这是一个print方法调用,而不是println)。
第二个数组的声明和实例化与int数组类似。它还有一个显式初始化的元素,另一个包含默认值。关键的区别在于这个数组有一个对象类型(特别是字符串),所以默认值为空。因此,最初您有sa[0]==null和sa[1]==null。接下来,下标0处的元素被指定引用字符串Hi。在循环期间,此代码将生成输出Hi-null。
基于所有这些,您可以看到选项A是正确的。
如果创建的是整数类型数组而不是int数组,则选项B可能是正确的,因为Integer是一个对象,而此类数组中的默认值将再次是空指针。但那没有完成,所以选项B是不正确的。
如果您认为创建为新Blah[x]的数组在下标0到x处有x+1元素,而不是在下标0到x-1处有x元素,那么您可能会倾向于选择选项C或选项D。
如果您认为访问未初始化的字符串可能会导致此处出现异常,那么选项E将非常诱人。这并非完全不合理。注意,如果对表达式“String is”+s a[1]求值,可能会看到输出字符串为空;但是,如果对“String is”+sa[1].toString()求值,实际上会得到一个NullPointerException。毕竟,sa[1]的值是null,尝试使用null引用对象肯定会失败。但是,字符串连接避开了这个问题,并有助于生成输出null,而不是引发异常。
正确的选择是A。