Ссылка на метод с полным вызовом конструктора как лямбда-выражение в Java - PullRequest
0 голосов
/ 03 декабря 2018

Я недавно столкнулся с конкурентным ответом лучше моего, который использует совершенно новый метод, называемый мне как замена лямбды.

Stream.generate(new AtomicInteger(1)::getAndIncrement)...

Я посмотрел Оракулспецификации на ссылки на метод и определены 4 типа:

  • ссылка на статический метод ContainingClass::staticMethodName
  • ссылка на метод экземпляра определенного объектаcontainingObject::instanceMethodName
  • Ссылка на метод экземпляра произвольного объекта определенного типа ContainingType::methodName
  • Ссылка на конструктор ClassName::new

Я борюсь склассифицировать этот.Я не нашел ни одного вопроса по SO или чего-либо соответствующего, объясненного в документах.Как бы это перевести в анонимный класс?

Мое подозрение:

IntStream.generate(new IntSupplier() {

    AtomicInteger atom = new AtomicInteger(1);

    @Override
    public int getAsInt() {
        return atom.getAndIncrement();
    }
})....

... Я не понимаю, как это возможно.На первый взгляд, я думаю, это выражение:

IntStream.generate(new IntSupplier() {

    @Override
    public int getAsInt() {
        return new AtomicInteger(1).getAndIncrement();
    }
})....

... но это не что иное, как () -> new AtomicInteger(1).getAndIncrement().

Где определяется этот вид выражения и как он будет точно переписан в лямбда / анонимном классе?

Ответы [ 3 ]

0 голосов
/ 03 декабря 2018

Это просто второй тип: ссылка на метод определенного объекта, никакой дополнительной логики за занавесом нет.

0 голосов
/ 03 декабря 2018

Ну new AtomicInteger(1) возвращает экземпляр, так что это второй.Точные детали того, как это переводится, зависят от конкретной реализации, но это один экземпляр, созданный и поддерживаемый JLS 15.13.3

Сначала, еслиВыражение ссылки на метод начинается с ExpressionName или Primary, это подвыражение оценивается

В простом английском языке часть перед :: оценивается , когда впервые встречается объявление .

Ваше предположение о том, как это переводится, является почти правильным, это все равно, что генерировать экземпляр вне самой функции и использовать его - поскольку он является фактически конечным, это разрешено.

0 голосов
/ 03 декабря 2018

Вы можете заменить

Stream.generate(new AtomicInteger(1)::getAndIncrement)...

на

AtomicInteger containingObject = new AtomicInteger(1);
Stream.generate(containingObject::getAndIncrement)...

, т. Е. Эта ссылка на метод относится ко второй категории ссылок на метод - Reference to an instance method of a particular object.

. Вам следуетобратите внимание, что создание экземпляра AtomicInteger не является частью реализации IntSupplier.Эквивалент Java 7 будет:

AtomicInteger aint = new AtomicInteger(1);
IntStream.generate(new IntSupplier() {

    @Override
    public int getAsInt() {
        return aint.getAndIncrement();
    }
})...

.

...