没有初始大小的字符串数组给出空指针异常
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!
但是为什么你甚至需要这种行为呢?它很简单。它适用于二维数组中的每个元素可以具有不同数量的元素的情况。潜在的用例场景是:
这种行为有很多很好的用例,例如优先级队列(每个优先级可以在队列中有不同数量的项目)、哈希表(它的溢出部分)等。
【讨论】:
以上是关于没有初始大小的字符串数组给出空指针异常的主要内容,如果未能解决你的问题,请参考以下文章