【问题标题】:char and int array differencechar 和 int 数组的区别
【发布时间】:2014-09-10 02:19:34
【问题描述】:

当我尝试打印未初始化的 static char 数组 时,它会给出运行时错误(空指针异常),而未初始化的 static 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
        System.out.println(arr); //it gives output as "null".
        }
    }

【问题讨论】:

  • 很确定,因为println() 的字符数组版本被重载并尝试将数组打印为字符串,而int[] 重载只是将其打印为数组。当使用char * 或通用void * 指针调用时,请参阅C++ 的std::cout::operator<<
  • 是的,这一切都与println 重载有关,与数组本身无关。 int[]char[] 基本相同,只是 int 是 4 字节有符号数据,char 是 2 字节无符号数据。

标签: java


【解决方案1】:

答案存在于PrintWriter源代码中(其中System.out是一个实例)。

首先,未初始化的数组作为参考变量,默认为null

println(char[])(最终)尝试在传入的数组上调用 .length。它为空,导致NullPointerExceptionprintln(char[])(最终)调用write(char[])

public void write(char buf[]) {
    write(buf, 0, buf.length);
}

没有匹配int[]println重载,但是有一个println(Object)。它(最终)尝试String.valueOf,传递null 引用,所以String.valueOf 采用null 并返回String "null"println(Object) 致电print(Object)

public void print(Object obj) {
    write(String.valueOf(obj));
}

【讨论】:

  • 异常处理成本很高。为什么不检查它是否为空?我知道这是设计师的问题,但我很好奇
  • 印刷也很贵,我猜?
  • System.out 是 PrintStream,而不是 PrintWriter。
【解决方案2】:

System.outPrintStream 的一个实例,这个类有一些重载的println 方法。在你的情况下:

  1. System.out.println(ch); 正在使用public void println(char x[])
  2. System.out.println(arr); 正在使用public void println(Object x)(没有public void println(int[] x) 方法,因此int[] 最接近的可用类型是println 可以使用的是Object)。

第二种方法是使用

String.valueOf(x);

获取我们要打印的对象的字符串表示,valueOf 方法的代码如下所示

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

所以它是空安全的(如果引用包含null,将返回字符串"null")。

第一种方法是在某种程度上使用

public void write(char cbuf[]) throws IOException {
    write(cbuf, 0, cbuf.length);
                 //    ^^^^^^^ this throws NPE
}

因为cbufnull cbuf.length 将抛出NullPointerException 因为null 没有length(或任何其他)字段。

【讨论】:

  • 那这不是库错误吗?
  • @usr 很难说。也许 Java 作者认为 print(Object) 是主要用于打印对象 state 的方法(借助其 toString 方法),因此打印 null 感觉不错,但他们希望从 print(char[])char 数组打印确切的字符,因为char[] 与String 相比不是那么常见的类型,因为null 感觉更像是错误而不是预期状态,所以他们决定通知程序员(并停止执行错误程序)扔NPE。但这不一定是真的。您需要询问 Java 设计人员。
  • @usr,可能,但如果你想使用Object 重载,那么你可以使用System.out.println((Object) chr)
  • @ıɯɐƃoʇǝızuǝʞ 是的,但这会打印数组的toString() 的结果,所以我们会看到类似[C@1db9742 的内容,而不是数组的内容。换句话说,println(new char[]{'f','o','o'}) 将打印 fooprintln((Object)new char[]{'f','o','o'}) 将打印 [C@1db9742
  • stackoverflow.com/questions/3881/… 这是调用者和库中的一个错误。
【解决方案3】:

这是两种不同的方法,它们的 API 完整地描述了行为。

public void println(Object x)首先调用String.valueOf,如果x为null则返回“null”。

见:

public void print(char[] c) 调用 print(char[] c) 方法,如果 c 为 null,则抛出 NullPointerException。

见:

【讨论】:

    【解决方案4】:

    您实际上是在调用两个独立的、重载的 System.out.println() 方法。 public void println(char[] x) 根据文档超载。 int[] 数组不存在特定的 println(Object x) 重载。

    因此,当在整数数组上调用 println() 时,会调用 public void println(Object x)。根据 Javadocs:

    此方法首先调用 String.valueOf(x) 以获取打印的 对象的字符串值,然后表现得好像它调用 print(String) 然后是 println()。

    由于字符串的值为null,因此该方法打印null。

    println() 方法在将字符数组作为参数时的工作方式有所不同。从表面上看,方法本身似乎很相似:

    打印一个字符数组,然后终止该行。这种方法 表现得好像它调用了 print(char[]) 然后 println()。

    但是,print(char[]) 方法在关键方面的行为完全不同:

    打印一个字符数组。字符转换为字节 根据平台的默认字符编码,而这些 字节完全按照 write(int) 方法的方式写入。

    因此,它调用了不同的方法。 print(char[]) 的文档明确指出,在您的情况下,您的异常会被抛出:

    抛出:NullPointerException - 如果 [输入参数] s 为空

    因此,行为差异的原因。

    有关 printlnprint 方法的更多信息,请参阅 Javadocs: http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#println()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-05
      • 2010-10-02
      相关资源
      最近更新 更多