23

This small program

public class Client {
    public static void main(String[] args) throws Exception {
        Arrays.asList(null);
    }
}

throws a NullPointerException.

Exception in thread "main" java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:221)
    at java.base/java.util.Arrays$ArrayList.<init>(Arrays.java:4322)
    at java.base/java.util.Arrays.asList(Arrays.java:4309)
    at org.example.Client.main(Client.java:10)

This program, however,

public static void main(String[] args) throws Exception {
    Arrays.asList(returnNull());
}

private static Object returnNull(){
    return null;
}

does not. Why do they behave differently?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Kousi
  • 440
  • 1
  • 3
  • 9
  • I think it has something to do with the method returning a null `Object` reference, while the plain old null is different? Intrigue question – RobOhRob Jun 11 '19 at 15:23
  • 6
    Nice one, in the second case the parameter is interpreted as an array of size 1 containing a `null` value , and in the first case as a `null` array . Don't know why and how, though. – Arnaud Jun 11 '19 at 15:25
  • Thanks @sotirios-delimanolis for formatting – Kousi Jun 11 '19 at 15:34
  • Related (or even a duplicate): [Calling Java varargs method with single null argument?](https://stackoverflow.com/questions/4028059/calling-java-varargs-method-with-single-null-argument) – Lino Jun 11 '19 at 15:46
  • `Type...` represents array of `Type` elements and since `null` can be assigned to any reference type it is OK for compiler to allow `Type... array = null`. But It is not OK to allow `T... array = someObject;` because `someObject` may not always hold value which can be assigned to `Type... array` (like `null`). So what compiler must do to make `T... array = someObject;` safe for all values? Simplest solution are often best so here simplest one is to add code which would wrap passed element in array like `Type... array = new Type[]{someObject}` regardless of actual value of `someObject`. – Pshemo Jun 11 '19 at 15:58
  • 1
    @Lino Well found. I do believe it's a duplicate – Michael Jun 11 '19 at 15:58
  • @Michael I refrained from hammering it myself, but if you also think it is one, then well done. Just didn't want to ego this :) – Lino Jun 11 '19 at 15:59

2 Answers2

16

The difference is just about how the argument is used at runtime:

The signature of asList is

public static <T> List<T> asList(T... a)

Arrays.asList(returnNull()) calls it with an Object. This clearly does not get interpreted as an array. Java creates an array at runtime and passes it as an array with one null element. This is equivalent to Arrays.asList((Object) null)

However, when you use Arrays.asList(null), the argument that's passed is taken to be an array, and, as the the method explicitly fails on null arrays passed as argument (see java.util.Arrays.ArrayList.ArrayList(E[])), you get that NPE.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
1

Signature of asList() is :- public static <T> List<T> asList(T... a)

So args requires Array of type T.

1st Case: When you put null as arg in asList the array will be pointing to null therefore throwing Exeption.
2nd Case: When you return a reference to any object which is pointing to null. Then it means array having a single Object, and that Object is pointing to null therefore not throwing Exception.

Tarun
  • 986
  • 6
  • 19