明日の関ジャバの資料作ってたら気になったので。(全く関係ない)
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
呼び出し側で配列作って渡してる。やっぱそうだよね。
現実逃避終わり。