没有初始大小的字符串数组给出空指针异常

Posted

技术标签:

【中文标题】没有初始大小的字符串数组给出空指针异常【英文标题】:String array without initial size gives null pointer exception 【发布时间】:2013-05-21 15:49:53 【问题描述】:

我只是在检查一些 OCJP 问题,并在字符串数组初始化和异常期间遇到了这种差异。

案例 1

try 
    String[][] b = new String[10][10]; // 1
    System.out.println(b[0][0]);       // 2
 catch (Exception e) 
    System.out.println("Exception during array 'b' initialization");
        e.printStackTrace();

案例 2

try 
    String[][] a = new String[10][]; // 3
    System.out.println(a[0][0]);     // 4
 catch (Exception e) 
    System.out.println("Exception during array 'a' initialization");
    e.printStackTrace();

第 2 行不会引发任何异常,而第 4 行会引发空指针异常。 第 2 行确实将值输出为 null

指定数组大小和不指定数组大小时,java初始化的默认值有区别吗?

【问题讨论】:

【参考方案1】:

这会将a 的类型设置为数组数组:

String[][] a

当你写作时

String[][] a = new String[10][];

你初始化了外部数组,但你没有创建内部数组,所以a[0]就是null

当你写作时

String[][] b = new String[10][10];

运行时还创建内部数组。它被描述为here in the specification:

在运行时,数组创建表达式的计算表现为 如下:

如果没有维度表达式,那么一定有一个数组 初始化器。

新分配的数组将使用提供的值进行初始化 由第 10.6 节中所述的数组初始值设定项。

数组初始化器的值变成数组的值 创作表达。

否则,没有数组初始化器,并且:

首先,从左到右计算维度表达式。如果有的话 的表达式求值突然完成,表达式 它的权利不被评估。

接下来,检查维度表达式的值。如果 任何 DimExpr 表达式的值小于零,则 抛出 NegativeArraySizeException。

接下来,为新数组分配空间。如果不足 分配数组的空间,数组创建的评估 表达式通过抛出 OutOfMemoryError 突然完成。

然后,如果出现单个 DimExpr,则创建一维数组 指定长度,并且数组的每个组件是 初始化为其默认值(§4.12.5)。

否则,如果出现 n 个 DimExpr 表达式,则创建数组 有效地执行一组深度为 n-1 的嵌套循环来创建 隐含的数组。

一个多维数组不需要有相同长度的数组 每个级别。

【讨论】:

and each component of the array is initialized to its default value 所以第 3 行应该分配 10 1-D arrays 并将 null 作为其每个元素的值,对吧?与第 1 行的情况相同。我说的对吗? 它将 null 分配给 a[0]a[1] 等。而第 1 行将 null 分配给 b[0][0]b[0][1] 等。【参考方案2】:
String[][] a = new String[3][];

相当于:

String[] a1 = null;
String[] a2 = null;
String[] a3 = null;
String[][] a = a1, a2, a3;

a[0][0] 类似于a1[0],它会抛出NPE。


你有两个选择:

将数组定义为:
String[][] a = new String[3][3];
或者在a中创建新数组:
a[0] = new String[2];
a[1] = new String[4];
a[2] = new String[3];

请注意,使用后一种方法,您将能够为内部数组设置不同的大小。

【讨论】:

【参考方案3】:

很好的发现。当你用两个参数初始化一个二维数组时,会发生什么:

String[][] a = new String[5][5]

但是当你指定第二个界限时,会发生什么:

String[][] a = new String[5][];

在您的第 4 行中,您会得到确切的 NullPointerException,因为:

String[][] a = new String[10][];
System.out.println(a[0][0]); // << a[0] is null!

但是为什么你甚至需要这种行为呢?它很简单。它适用于二维数组中的每个元素可以具有不同数量的元素的情况。潜在的用例场景是:

这种行为有很多很好的用例,例如优先级队列(每个优先级可以在队列中有不同数量的项目)、哈希表(它的溢出部分)等。

【讨论】:

以上是关于没有初始大小的字符串数组给出空指针异常的主要内容,如果未能解决你的问题,请参考以下文章

填充listView时数组自适应给出空指针异常

为啥我的数组列表即使在初始化后也会抛出空指针异常?

常见异常总结

Java常见异常

常见java异常

java常见异常总结