明日の関ジャバの資料作ってたら気になったので。(全く関係ない)
javac 11.0.4
可変長引数のメソッドを持つVaragsクラスとそれを呼び出すInvokerクラスがあってさ。
class Varargs { static void methodX(Object... args) {} static void methodY(Object[] args) {} } class Invoker { void methodA() { Varargs.methodX(); } void methodB() { Varargs.methodX(new Object()); } }
Varargs.methodX と Varargs.methodY の違いって、可変長で作ってたら引数が空とか配列にしなくても渡せたりとかするわけだけど、外から見えるコンパイル結果に違いがないと、そんな区別ってつかないはずで。メソッド内は配列で扱ってるのは間違いないのだけど。
なので javap してみて。
static void methodX(java.lang.Object...);
descriptor: ([Ljava/lang/Object;)V
flags: (0x0088) ACC_STATIC, ACC_VARARGS
Code:
stack=0, locals=1, args_size=1
0: return
static void methodY(java.lang.Object[]);
descriptor: ([Ljava/lang/Object;)V
flags: (0x0008) ACC_STATIC
Code:
stack=0, locals=1, args_size=1
0: return
descriptor は同じで、 ACC_VARARGS がついてる。classファイルのフォーマット眺める。
The ACC_VARARGS flag indicates that this method takes a variable number of arguments at the source code level. A method declared to take a variable number of arguments must be compiled with the ACC_VARARGS flag set to 1. All other methods must be compiled with the ACC_VARARGS flag set to 0.
なるほど(ふいんき)。
あとInvokerも javap って眺める。
void methodA();
descriptor: ()V
flags: (0x0000)
Code:
stack=1, locals=1, args_size=1
0: iconst_0
1: anewarray #2 // class java/lang/Object
4: invokestatic #3 // Method Varargs.methodX:([Ljava/lang/Object;)V
7: return
void methodB();
descriptor: ()V
flags: (0x0000)
Code:
stack=5, locals=1, args_size=1
0: iconst_1
1: anewarray #2 // class java/lang/Object
4: dup
5: iconst_0
6: new #2 // class java/lang/Object
9: dup
10: invokespecial #1 // Method java/lang/Object."<init>":()V
13: aastore
14: invokestatic #3 // Method Varargs.methodX:([Ljava/lang/Object;)V
17: return
呼び出し側で配列作って渡してる。やっぱそうだよね。
現実逃避終わり。