Ответ 1
Даже после того, как почти час назад я ударил головой в байт-код, мне не удалось прийти к разумному выводу о том, почему это происходит. Удивительно, что вы изменили свой метод:
private void runTest() {
Worker worker = new Worker();
run(() -> worker.print(field -> new SomeClass(field)));
Function<Object, Object> function = SomeClass::new;
run(() -> worker.print(function));
}
работает отлично. Кроме того, избавление от вызова метода run()
и просто вызов worker.print()
:
private void runTest() {
Worker worker = new Worker();
worker.print(field -> new SomeClass(field));
worker.print(SomeClass::new);
}
также работает.
Похоже, что использование ссылки на конструктор, как в вашем случае, не может передать охватывающий экземпляр класса Test
конструктору SomeClass
, который требуется. Хотя два случая здесь могут передать экземпляр Test
в конструктор SomeClass
.
Но я не мог прийти к этой причине. Вышеприведенные рассуждения вполне могут ошибаться. Но я только что пришел к этому, достигнув этого рабочего подхода.
Возможно, вы захотите пройти lambda translation, чтобы понять внутреннюю работу. Я все еще не очень понимаю, как переводятся слова lambdas и методы.
Я нашел поток в списке рассылки лямбда об аналогичной проблеме. Кроме того, этот SO post также связан.
Следующий метод runtTest()
:
public void runTest() {
Worker worker = new Worker();
run(() -> worker.print((field) -> new SomeClass(field)));
run(() -> worker.print(SomeClass::new));
Function<Object, Object> func = SomeClass::new;
run(() -> worker.print(func));
worker.print(SomeClass::new);
}
Скомпилируется в следующий байт-код:
public void runTest();
Code:
0: new #2 // class SO$Worker
3: dup
4: invokespecial #3 // Method SO$Worker."<init>":()V
7: astore_1
8: aload_0
9: aload_0
10: aload_1
11: invokedynamic #4, 0 // InvokeDynamic #0:run:(LSO;LSO$Worker;)Ljava/lang/Runnable;
16: invokevirtual #5 // Method run:(Ljava/lang/Runnable;)V
19: aload_0
20: aload_1
21: invokedynamic #6, 0 // InvokeDynamic #1:run:(LSO$Worker;)Ljava/lang/Runnable;
26: invokevirtual #5 // Method run:(Ljava/lang/Runnable;)V
29: aload_0
30: invokedynamic #7, 0 // InvokeDynamic #2:apply:(LSO;)Ljava/util/function/Function;
35: astore_2
36: aload_0
37: aload_1
38: aload_2
39: invokedynamic #8, 0 // InvokeDynamic #3:run:(LSO$Worker;Ljava/util/function/Function;)Ljava/lang/Runnable;
44: invokevirtual #5 // Method run:(Ljava/lang/Runnable;)V
47: aload_1
48: aload_0
49: invokedynamic #7, 0 // InvokeDynamic #2:apply:(LSO;)Ljava/util/function/Function;
54: invokevirtual #9 // Method SO$Worker.print:(Ljava/util/function/Function;)V
57: return
Я вижу, что только второй вызов метода run()
не передает аргумент LSO
, а другие его передают. Вы можете запустить команду - javap -c -s -verbose Test
, чтобы увидеть методы Bootstrap для #0
, #1
и т.д. Я думаю, мы можем определенно сказать, что это ошибка. Возможно, вы можете записать файл.