18

When I try to print the uninitialized static char array it gives run time error (Null pointer exception) whereas the uninitialized static int array gives null value. Why?

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".
        }
    }
Pshemo
  • 122,468
  • 25
  • 185
  • 269
Shashank Agarwal
  • 1,122
  • 1
  • 8
  • 24
  • 7
    pretty sure because the char array version of `println()` is overloaded and tries to print the array as a string, whereas the `int[]` overload simply prints it as an array. Refer to C++'s `std::cout::operator<<` when called with `char *` or a generic `void *` pointer. – The Paramagnetic Croissant Jul 18 '14 at 20:52
  • Yep, all has to do with `println` overloading, and nothing to do with the arrays themselves. `int[]` and `char[]` are essentially identical save for the fact that `int` is 4-byte signed data and `char` is 2-byte unsigned data. – Hot Licks Jul 18 '14 at 20:55

4 Answers4

15

The answer exists in the PrintWriter source code (of which System.out is an instance).

Start with the fact that the uninitialized arrays, as reference variables, are given the default of null.

The println(char[]) (eventually) attempts to call .length on the passed in array. It's null, resulting in the NullPointerException. println(char[]) (eventually) calls write(char[]):

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

There is no overload of println matching int[], but there is a println(Object). There it (eventually) attempts String.valueOf, passing the null reference, so String.valueOf takes the null and returns the String "null". println(Object) calls print(Object):

public void print(Object obj) {
    write(String.valueOf(obj));
}
rgettman
  • 176,041
  • 30
  • 275
  • 357
15

System.out is an instance of PrintStream and this class has a few overloaded println methods. In your case:

  1. System.out.println(ch); is using public void println(char x[])
  2. System.out.println(arr); is using public void println(Object x) (there is no public void println(int[] x) method so the closest available type for int[] which println can use is Object).

The second method is using

String.valueOf(x);

to get a string representation of the object we want to print and the code of the valueOf method looks like

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

so it is null-safe (will return the string "null" if the reference holds null).

The first method is at some level using

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

and because cbuf is null cbuf.length will throw NullPointerException because null doesn't have length (or any other) field.

Cyanfish
  • 3,907
  • 1
  • 14
  • 12
Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • Isn't this a library bug then? – usr Jul 18 '14 at 22:04
  • @usr It is hard to tell. Maybe Java authors think of `print(Object)` as method mostly used to print *state* of object (with help of its `toString` method) so printing `null` feel right, but from `print(char[])` they expect to print exact characters from `char` array and since `char[]` is not so common type compared to String being it `null` feels more like bug than intended state, so they decide to inform programmer about it (and stop execution buggy program) by throwing NPE. But that doesn't have to be true. You would need to ask Java designers. – Pshemo Jul 18 '14 at 22:26
  • @usr, possibly, although if you wanted to use the `Object` overload then you could do `System.out.println((Object) chr)`. – Octavia Togami Jul 18 '14 at 22:36
  • @ıɯɐƃoʇǝızuǝʞ yes, but this would print result of `toString()` of array so we would see something like `[C@1db9742` instead of content of array. In other words `println(new char[]{'f','o','o'})` will print `foo` while `println((Object)new char[]{'f','o','o'})` will print `[C@1db9742`. – Pshemo Jul 18 '14 at 22:38
  • That's what you'd get with the `int[]` array too, which is why there's `Arrays.toString()`. – Octavia Togami Jul 19 '14 at 02:59
  • Isn't a NPE always considered a bug in the Java world? It isn't like the library devs have *decided* here to throw that exception. They didn't think about this case and crash in internal code. Thanks to luck this is not a corruption or security problem. – usr Jul 19 '14 at 09:46
  • @usr It's not a bug. The method specification says it will print the characters of the array. If the caller neglects to pass an actual array (by passing null instead), it's right that they should get an exception thrown at them. – Boann Jul 19 '14 at 11:39
  • @usr Yes NPE represents a bug in code, but it doesn't mean that bug is in line which threw NPE. Methods author may decide that method should not accept `null`s and if they will get `null` as argument rather than handling it they would stop executing potentially flawed/bugged code (which used this method) by throwing NPE. So bug is not *in method itself*, but in *code which used it*. – Pshemo Jul 19 '14 at 11:47
  • 1
    http://stackoverflow.com/questions/3881/illegalargumentexception-or-nullpointerexception-for-a-null-parameter It's a bug in both the caller as well as the library. – usr Jul 19 '14 at 15:23
  • @usr Very interesting post but it is more like discussion than question/100%-correct-answer. If you take a look at this answers http://stackoverflow.com/a/8160/1393766, http://stackoverflow.com/a/6358/1393766 you will notice that throwing NPE instead if IAE may be Java creators way of handling `null` as incorrect argument (at least it seems that Joshua Bloch - author of collection framework, or "Effective Java" book - is in favour of it), so it doesn't have to mean that it is bug in library (but definitely it is bug in caller code). – Pshemo Jul 20 '14 at 01:19
2

These are two different methods, and their APIs describe the behavior fully.

public void println(Object x) calls String.valueOf at first, which returns "null" if x is null.

See:

public void print(char[] c) calls the print(char[] c) method which throws NullPointerException if c is null.

See:

NESPowerGlove
  • 5,496
  • 17
  • 28
0

You are actually calling two separate, overloaded System.out.println() methods. public void println(char[] x) is overloaded as per the documentation. No specific overloading of println(Object x) exists for the int[] arrays.

So, when println() is called on an integer array, public void println(Object x) is called. According to the Javadocs:

This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().

Since the value of the string is null, the method prints null.

The println() method works somewhat differently when it takes a character array as a parameter. Superficially, the method itself seems similar:

Prints an array of characters and then terminate the line. This method behaves as though it invokes print(char[]) and then println().

However, the print(char[]) method behaves quite differently in key ways:

Prints an array of characters. The characters are converted into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method.

Thus, it calls a different method. The documentation for print(char[]) explicitly states that in your situation, your exception is thrown:

Throws: NullPointerException - If [input parameter] s is null

Hence, the cause of the difference in behavior.

See Javadocs for more information about the println and print methods: http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#println()

La-comadreja
  • 5,627
  • 11
  • 36
  • 64