[Java] Precautions when converting variable-length argument parameters into an array

I think that if you are not careful when playing with reflection or J Mockit's Deencapsulation, it will be a good point, so I summarized it.

For the time being, move with various patterns

Main.java



public class Main {

    public static void main(String[] args) {

        // 1
        test(1, "a", "b", "c");

        // 2
        test(2, new String[] { "a", "b", "c" });

        // 3
        test(3, new String[] { "a", "b", "c" }, "d");

        // 4
        test(4, new int[] { 1, 2, 3 });

    }

    private static void test(int number, Object... args) {

        System.out.println("No." + number + " length = " + args.length);

    }

}

Values are passed to the variables of the variable length arguments in various patterns, and the size of the received parameters is output. How will it be output to the console?

Output result

console


No.1 length = 3
No.2 length = 3
No.3 length = 2
No.4 length = 1

Commentary

It is easy to understand if you are aware that the definition of variadic arguments is actually an array and think about what it will look like at compile time.

The recipient is converted to a method with the following arguments at compile time.

private static void test(int number, Object[] args) {
    ...
}

No.1

Converted to the receiving array at compile time.

test(1, new Object[]{"a", "b", "c"});

The size will be 3.

No.2

No conversion is done because the array is already covariant.

test(2, new String[]{"a", "b", "c"});

The size will be 3.

No.3

Converted to the receiving array at compile time.

test(3, new Object[] { new String[] { "a", "b", "c" }, "d" });

The size will be 2.

No.4

Although it is already an array, the primitive type array cannot be cast to the Object array as it is, so it is converted to the state wrapped in the Object array at compile time.

test(4, new Object[] { new int[] { 1, 2, 3 } });

The size will be 1.

Afterword

--If you want to pass the array itself as one data in No.2, you can do it by explicitly casting as follows.

//No.2 length = 1
test(2, (Object) new String[]{"a", "b", "c"});

--If you have trouble with strange behavior, you may try decompiling (java → class → java). The java8 compatible decompiler seems to have various features such as CFR, FernFlower, Procyon, etc. → I want to write an article someday

Recommended Posts

[Java] Precautions when converting variable-length argument parameters into an array
[Java] Shallow copy and deep copy when converting an array to List
<Java> When creating a fixed-length (row) * variable-length (column) two-dimensional array
Precautions when using Mockito.anyString as an argument when Mocking with Mockito
Java learning memo (creating an array)
[Java] Declare and initialize an array
When seeking multiple in a Java array
Pass parameters when debugging vscode java. [Note]
Map without using an array in java
Compare the elements of an array (Java)
[Java] Precautions when comparing character strings with character strings
Precautions when migrating from VB6.0 to JAVA
Summary of good points and precautions when converting Java Android application to Kotlin