Почему функция Kotlin с параметрами по умолчанию создает метод с неиспользуемым параметром
Смотрите этот пример кода в Kotlin:
fun foo(bar: Int = 0, baz: Int) {
/* ... */
}
После декомпиляции кода Java (Tools → Kotlin → Show Kotlin Bytecode → Decompile) я получил следующий код
public static final void foo(int bar, int baz) {
}
// $FF: synthetic method
// $FF: bridge method
public static void foo$default(int var0, int var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var0 = 0;
}
foo(var0, var1);
}
Я заметил, что полученный Java-метод имеет неиспользуемый параметр Object var3
.
Мне кажется, что это может быть связано с функциями в классе, но при декомпиляции этого кода
class Foo {
fun foo(bar: Int = 0, baz: Int) {
/* ... */
}
}
Я получил этот код
public final class Foo {
public final void foo(int bar, int baz) {
}
// $FF: synthetic method
// $FF: bridge method
public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = 0;
}
var0.foo(var1, var2);
}
}
Как вы видите, параметр Object
по-прежнему не используется и просто сидит там.
При дополнительных тестах я заметил такое же поведение для методов расширения. То же самое происходит, когда последний параметр по умолчанию (т.е. fun foo(bar: Int, baz: Int = 0) {}
)
Я также провел базовый тест, чтобы проверить, что это за значение, установленное при вызове этой функции, используя код ниже
fun main(args: Array<String>) {
foo(baz = 2)
}
и
class Something {
init {
foo(baz = 2)
}
}
После декомпиляции я получил следующий код
public static final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
foo$default(0, 2, 1, (Object)null);
}
и
public final class Something {
public Something() {
FooKt.foo$default(0, 2, 1, (Object)null);
}
}
Что еще меньше имеет смысл.
Мой вопрос: почему Kotlin генерирует неиспользуемый параметр для функций с параметрами по умолчанию? Это ошибка?
Ответы
Ответ 1
В соответствии с этим, в настоящее время он не используется, но зарезервирован для добавления супервызов с настройками по умолчанию позже.
Вы можете увидеть это в действии здесь:
open class Foo {
open fun foo(bar: Int = 0, baz: Int) {
/* ... */
}
}
class Blah: Foo() {
override fun foo(bar: Int, baz: Int) {
}
}
который сгенерирует байт-код-к-Java Foo
из:
public class Foo {
public void foo(int bar, int baz) {
}
// $FF: synthetic method
// $FF: bridge method
public static void foo$default(Foo var0, int var1, int var2, int var3, Object var4) {
if(var4 != null) {
throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: foo");
} else {
if((var3 & 1) != 0) {
var1 = 0;
}
var0.foo(var1, var2);
}
}
}