Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 3 dots parameter (varargs) behavior when passed no arguments or null

I tried this and get weird behavior from JAVA, can someone explain this for me?

boolean testNull(String... string) {     if(string == null) {         return true;     } else {         System.out.println(string.getClass());         return false;     } }  boolean callTestNull(String s) {     return testNull(s); } 

Then I have test case:

    @Test     public void test_cases() {         assertTrue(instance.testNull(null)); // NULL         assertFalse(instance.testNull()); // NOT NULL         assertFalse(instance.callTestNull(null)); // NOT NULL     } 

The question is if I call testNull() directly with parameter null, I will get true back, but if call callTestNull() with null, which calls testNull(), it tells me the parameter is not null, but empty array.

like image 696
Jaiwo99 Avatar asked Jul 17 '13 14:07

Jaiwo99


People also ask

What does the 3 dots mean in Java?

The "Three Dots" in java is called the Variable Arguments or varargs. It allows the method to accept zero or multiple arguments. Varargs are very helpful if you don't know how many arguments you will have to pass in the method.

Can Varargs take 0 arguments?

Syntax of Varargs A variable-length argument is specified by three periods or dots(…). This syntax tells the compiler that fun( ) can be called with zero or more arguments.

What is the rule for using varargs in Java?

While using the varargs, you must follow some rules otherwise program code won't compile. The rules are as follows: There can be only one variable argument in the method. Variable argument (varargs) must be the last argument.

What symbol is used for a Varargs method parameter?

In Java, an argument of a method can accept arbitrary number of values. This argument that can accept variable number of values is called varargs. In order to define vararg, ... (three dots) is used in the formal parameter of a method.


1 Answers

The question is if I call testNull() directly with parameter null, I will get true back, but if call callTestNull() with null, which calls testNull(), it tells me the parameter is not null, but empty array.

Yes. If you call it with an argument with a compile-time type of String, the compiler knows that can't be a String[], so it wraps it within a string array. So this:

String x = null; testNull(x); 

is equivalent to:

String x = null; testNull(new String[] { x }); 

At this point, the (misleadingly-named) string parameter will have a non-null value - instead, it will refer to an array of size 1 whose sole element is a null reference.

However, when you use the null literal directly in the method call, that's directly convertible to String[], so no wrapping is performed.

From JLS section 15.12.4.2:

If the method being invoked is a variable arity method m, it necessarily has n > 0 formal parameters. The final formal parameter of m necessarily has type T[] for some T, and m is necessarily being invoked with k ≥ 0 actual argument expressions.

If m is being invoked with k ≠ n actual argument expressions, or, if m is being invoked with k = n actual argument expressions and the type of the k'th argument expression is not assignment compatible with T[], then the argument list (e1, ..., en-1, en, ..., ek) is evaluated as if it were written as (e1, ..., en-1, new |T[]| { en, ..., ek }), where |T[]| denotes the erasure (§4.6) of T[].

(Emphasis mine.)

The bit I've emphasized is why the wrapping only happens when the compile-time type of the argument is String, not the null type.

like image 99
Jon Skeet Avatar answered Sep 22 '22 11:09

Jon Skeet