Гость
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Забавное поведение method reference / 11 сообщений из 11, страница 1 из 1
03.03.2021, 00:57
    #40050089
rabiter
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Всем привет!

Наткнулся на такой фокус покус.
есть два класса - предок и потомок (в РАЗНЫХ ПАКЕТАХ, это важно):
Код: java
1.
2.
3.
4.
5.
public class Parent {
    protected String getString() {
        return ".....";
    }
}


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public class Child extends Parent {

    public class Value  {
        public Value() {
            Supplier<String> var = Child.this::getString;
        }
    }
}



запускаем тест:
Код: java
1.
new Child().new Value();


получаем исключение:
java.lang.BootstrapMethodError: java.lang.IllegalAccessError: tried to access method com.p.Parent.getString()Ljava/lang/String; from class com.Child$Value

хмм.., теперь следим за руками, меняем method reference
Код: java
1.
Child.this::getString;

на lambda
Код: java
1.
() -> Child.this.getString();


т.е. получается
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public class Child extends Parent {

    public class Value  {
        public Value() {
            Supplier<String> var = () -> Child.this.getString();
        }
    }
}


запускаем тест - все работает!
выходит method reference и lambda не совсем одно и то же? печалька..
...
Рейтинг: 0 / 0
03.03.2021, 07:58
    #40050107
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Поправил ваш пример до компилируемого состояния (все три класса - в разных пакетах):
Parent.java
Код: java
1.
2.
3.
4.
5.
6.
package local.p;
public class Parent {
  protected String getString() {
     return "class p.Parent";
  }
}

Child.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
package local.c;
public class Child extends local.p.Parent {
  public void Value() {
    java.util.function.Supplier<String> v = Child.this::getString;
    System.out.println("Method reference: " + v);

    v = () -> Child.this.getString();
    System.out.println("           Lamba: " + v);
  }
}

Main.java
Код: java
1.
2.
3.
4.
5.
6.
package local.m;
public class Main {
  public static void main(String[] args) {
    (new local.c.Child()).Value();
  }
}

Код: plaintext
1.
2.
3.
4.
5.
6.
> java -showversion -cp bin local.m.Main
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_282-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.282-b08, mixed mode)

Method reference: local.c.Child$$Lambda$1/531885035@1218025c
           Lamba: local.c.Child$$Lambda$2/135721597@87aac27
и
Код: plaintext
1.
2.
3.
4.
5.
> java -showversion -cp bin local.m.Main
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9+11)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9+11, mixed mode, sharing)
Method reference: local.c.Child$$Lambda$1/0x0000000840060840@49476842
           Lamba: local.c.Child$$Lambda$2/0x0000000840060c40@27c170f0
...
Рейтинг: 0 / 0
03.03.2021, 12:26
    #40050230
rabiter
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Basil A. Sidorov,

спасибо! так у вас воспроизвелось? если именно не с лямбдой, а с method reference? Я такой нюанс уже второй раз наблюдаю, первый раз было несколько лет назад, на другом примере. Как это происходит, видишь такой в коде лямбду, IDEA предлагает заменить на reference. Ну и ты такой меняешь, что такого. А ошибка потом в runtime происходит, ты даже об этом узнать можешь намного позже. Сейчас мне юнит тесты помогли, так что я сразу заметил.
...
Рейтинг: 0 / 0
03.03.2021, 12:32
    #40050241
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
По моему, тексты классов достаточно короткие, чтобы понять: нет, не воспроизвелось.
Ну или ткнуть пальцев те места кода, которые отличаются от вашей задумки.
...
Рейтинг: 0 / 0
03.03.2021, 15:50
    #40050371
rabiter
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Basil A. Sidorov,

сейчас только заметил, вы заменили внутренний класс Value на метод Value. Вот поправленные примеры:
Parent.java
Код: java
1.
2.
3.
4.
5.
6.
package local.p;
public class Parent {
  protected String getString() {
     return "class p.Parent";
  }
}

Child.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package local.c;
public class Child extends local.p.Parent {
    public class Value {
        public Value() {
            java.util.function.Supplier<String> v = Child.this::getString;
            System.out.println("Method reference: " + v);

            v = () -> Child.this.getString();
            System.out.println("           Lamba: " + v);
        }

    }
}

Main
Код: java
1.
2.
3.
4.
5.
6.
package local.m;
public class Main {
  public static void main(String[] args) {
   new local.c.Child().new Value();
  }
}



должно свалиться на
Код: java
1.
java.util.function.Supplier<String> v = Child.this::getString;
...
Рейтинг: 0 / 0
03.03.2021, 15:51
    #40050373
rabiter
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
ну а если method reference заменить на lambda - то все рабоатет
...
Рейтинг: 0 / 0
03.03.2021, 16:21
    #40050383
Псевдомизантроп
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
rabiter

выходит method reference и lambda не совсем одно и то же?


Нет, не одно и то же
...
Рейтинг: 0 / 0
03.03.2021, 16:57
    #40050390
rabiter
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Псевдомизантроп,

да, похоже на то. Лямбда понятно - создает анонимную имплементацию интерфейса, в принципе, ничего нового, просто синтаксис. А я наивный думал method reference тоже так же имплементирован. Походу нет.
И самая подстава, что такая ошибка-то runtime а не compile. А IDEA такая: не хочешь немного method reference вместо лямбд?))
...
Рейтинг: 0 / 0
03.03.2021, 18:53
    #40050420
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Бага(?) javac JVM8:
чуть подрезал комстроку javac JVM11
Код: plaintext
jdk11/bin/javac -source 8 -target 8 -bootclasspath jre8/lib/rt.jar src/*.java
и
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_282-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.282-b08, mixed mode)

Method reference: local.c.Child$Value$$Lambda$1/531885035@1218025c
           Lamba: local.c.Child$Value$$Lambda$2/135721597@87aac27
local.c.Child$Value@3e3abc88

P.S.
Реализация лямбд отдаётся "на откуп" разработчикам JDK/JVM: могут сделать так, могут - сяк.
...
Рейтинг: 0 / 0
03.03.2021, 23:08
    #40050491
rabiter
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Basil A. Sidorov
Бага(?) javac JVM8:
чуть подрезал комстроку javac JVM11
Код: plaintext
jdk11/bin/javac -source 8 -target 8 -bootclasspath jre8/lib/rt.jar src/*.java
и
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_282-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.282-b08, mixed mode)

Method reference: local.c.Child$Value$$Lambda$1/531885035@1218025c
           Lamba: local.c.Child$Value$$Lambda$2/135721597@87aac27
local.c.Child$Value@3e3abc88

P.S.
Реализация лямбд отдаётся "на откуп" разработчикам JDK/JVM: могут сделать так, могут - сяк.


ну может быть и бага в JVM... у меня тоже восьмерка, не проверял на других версиях

Код: plaintext
1.
2.
3.
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)

может выложу баг, куда бы написать только, надо погуглить)
...
Рейтинг: 0 / 0
04.03.2021, 08:26
    #40050531
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Забавное поведение method reference
Тестовый пример, если вы не заметили, успешно запустился под Java 8. Байткод создавал javac из jdk11, но с -target 8.
Следовательно, проблема не в вашем примере и не в JVM Java 8, а в javac jdk8.
Замечу, что есть ещё и ecj и OpenJ9, но мне уже в ломы ковырять дальше.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Забавное поведение method reference / 11 сообщений из 11, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]