Вызов методов по умолчанию из лямбда-выражений

Есть ли способ вызвать метод по умолчанию при определении лямбда?

E.g.

@FunctionalInterface
public interface StringCombiner {
    String combine(String s1, String s2);

   default String bar(String s1, String s2) {
        return combine(s1,s2);
   };

}

Я хочу сделать что-то вроде этого:

StringCombiner sc = (s1, s2) -> /** I want to call bar() here **/

person almendar    schedule 14.02.2014    source источник


Ответы (1)


Это приведет к StackOverflowError: bar вызывает combine, который вызывает bar, который вызывает combine...

Вам нужно рекурсивно ссылаться на sc в его определении (вы не можете использовать this в лямбде для ссылки на объект, созданный лямбдой). Я считаю, что это возможно только в переменной экземпляра или класса. Таким образом, это может выглядеть так:

@FunctionalInterface
public interface StringCombiner {
    String combine(String s1, String s2);
    default String bar(String s1, String s2) { return "bar"; }
}

//Note: you need the static block to avoid a "self-reference" compilation error
static StringCombiner sc;
static {
  sc = (s1, s2) -> sc.bar(s1, s2) + s1 + s2;
}

public static void main(String[] args) {
    System.out.println(sc.combine("a", "b"));
}

который печатает barab.

person assylias    schedule 14.02.2014
comment
Ооо, извините, да, я забыл удалить вызов комбайна из панели. Однако здесь это не имеет значения. В любом случае вы ответили на мой вопрос. Спасибо! :) - person almendar; 14.02.2014
comment
не работает из-за ссылки на себя в инициализаторе - person mysh; 18.08.2015
comment
@mysh Действительно, спасибо - он скомпилирован с более ранними версиями Java 8, которые использовались, когда я впервые опубликовал ответ. В последней версии вам необходимо разделить декларацию и инициализацию. - person assylias; 18.08.2015