Java char和int数组差异
当我试图打印未初始化的静态字符数组时,它会给出运行时错误(空指针异常),而未初始化的静态int数组会给出空值。为什么?Java char和int数组差异,java,Java,当我试图打印未初始化的静态字符数组时,它会给出运行时错误(空指针异常),而未初始化的静态int数组会给出空值。为什么? public class abc { static int arr[]; static char ch[]; public static void main(String[] args) { System.out.println(ch); //it gives null pointer exception at run time
public class abc {
static int arr[];
static char ch[];
public static void main(String[] args) {
System.out.println(ch); //it gives null pointer exception at run time
System.out.println(arr); //it gives output as "null".
}
}
答案存在于
PrintWriter
源代码中(其中System.out
就是一个例子)
首先,未初始化的数组作为引用变量,默认值为null
println(char[])
(最终)尝试对传入的数组调用.length
。它为null,导致出现NullPointerException
println(char[])
(最终)调用write(char[])
:
匹配的int[]
没有重载println
,但有一个println(对象)
。在那里,它(最终)尝试String.valueOf
,传递null
引用,因此String.valueOf
接受null
,并返回字符串“null”
println(对象)
调用print(对象)
:
System.out
是PrintStream
的一个实例,这个类有一些重载的println
方法。就你而言:
System.out.println(ch)代码>正在使用public void println(char x[])
System.out.println(arr)
正在使用公共void println(Object x)
(没有公共void println(int[]x)
方法,因此println
可以使用的int[]
最接近的可用类型是Object
)
第二种方法是使用
String.valueOf(x);
要获得要打印的对象的字符串表示形式,方法的valueOf
的代码如下所示
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
因此它是空安全的(如果引用保持空,则返回字符串“null”
)
第一种方法是在某种程度上使用
public void write(char cbuf[]) throws IOException {
write(cbuf, 0, cbuf.length);
// ^^^^^^^ this throws NPE
}
因为cbuf
是null
cbuf.length
将抛出NullPointerException,因为null
没有length
(或任何其他)字段。这是两种不同的方法,它们的API充分描述了行为
public void println(对象x)
首先调用String.valueOf,如果x为null,则返回“null”
见:
public void print(char[]c)
调用print(char[]c)方法,如果c为null,该方法将抛出NullPointerException
见:
您实际上在调用两个独立的、重载的System.out.println()
方法<代码>公共void println(char[]x)
根据文档重载。对于int[]
数组,不存在println(Object x)
的特定重载
因此,当对整数数组调用println()
时,将调用public void println(Object x)
。根据Javadocs:
此方法在第一个String.valueOf(x)处调用以获取打印的
对象的字符串值,然后其行为就像调用打印(字符串)
然后是println()
由于该字符串的值为null
,因此该方法将打印null
当使用字符数组作为参数时,println()
方法的工作方式有所不同。从表面上看,该方法本身似乎相似:
打印一个字符数组,然后终止该行。这种方法
其行为就像调用print(char[]),然后调用println()
但是,print(char[])
方法在关键方面的行为非常不同:
打印字符数组。字符被转换成字节
根据平台的默认字符编码
字节的写入方式与write(int)方法完全相同
因此,它调用不同的方法。print(char[])
的文档明确指出,在您的情况下,会引发异常:
抛出:NullPointerException-如果[input parameter]s为null
因此,导致行为差异的原因
有关println
和print
方法的更多信息,请参见Javadocs:
非常确定,因为println()
的字符数组版本重载并尝试将数组打印为字符串,而int[]
重载只是将其打印为数组。参考C++的std::cout::operatorYep,所有这些都与println
重载有关,而与数组本身无关int[]
和char[]
本质上是相同的,只是int
是4字节的有符号数据,char
是2字节的无符号数据。异常处理非常昂贵。。为什么不检查它是否为空?我知道这对设计师来说是个问题,但我很好奇打印也很贵,我猜?System.out是一个打印流,不是一个打印编写器。那么这不是一个库错误吗?@usr很难说。也许Java作者认为print(Object)
是一种主要用于打印对象状态的方法(借助其toString
方法),所以打印null
感觉不错,但是从print(char[])
中,他们希望打印char
数组和char[]中的精确字符
与字符串相比不是很常见的类型,因为它null
感觉更像是bug而不是预期状态,所以他们决定通过抛出NPE通知程序员它(并停止执行有bug的程序)。但这不一定是真的。您可能需要询问Java设计人员。@usr,虽然如果您想使用对象
重载,那么您可以执行System.out.println((Object)chr)
@oʇoʇǝzuʞ是的,但这会打印数组的toString()
的结果,因此我们会看到类似[C@1db9742public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
public void write(char cbuf[]) throws IOException {
write(cbuf, 0, cbuf.length);
// ^^^^^^^ this throws NPE
}