without - java функциональный интерфейс



Причуда наследования функционального интерфейса (1)

У меня есть пользовательский интерфейс, который я использовал в течение некоторого времени, который выглядит примерно так:

public interface Function<T, R> {
    R call(T input);
}

Я бы хотел дооснастить этот интерфейс как Java- Function так и Function Guava, сохранив при этом FunctionalInterface . Я думал, что у меня было идеальное расположение:

@FunctionalInterface
public interface Function<T, R> extends
        java.util.function.Function<T, R>,
        com.google.common.base.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}

Оба суперинтерфейса объявляют один и тот же метод apply() , который был реализован в моем интерфейсе, оставляя только абстрактный метод call() . Странно, это не скомпилируется, говорит мне

Неверная аннотация @FunctionalInterface; Функция <T, R> не является функциональным интерфейсом

Тем не менее, следующие варианты компилируются просто отлично:

@FunctionalInterface
public interface Function<T, R> extends
        java.util.function.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}

@FunctionalInterface
public interface Function<T, R> extends
        com.google.common.base.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}

public interface Function<T, R> extends
        java.util.function.Function<T, R>,
        com.google.common.base.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}

@FunctionalInterface
public interface Function<T, R> extends
        java.util.function.Function<T, R>,
        com.google.common.base.Function<T, R> {

    @Override
    R apply(T input);
}

Есть ли причина, по которой первая версия не скомпилируется?


Как указано в комментариях, он прекрасно компилируется с компилятором Oracle. Это ошибка затмения.

В ожидании исправления ошибки я лично удалю аннотацию @FunctionalInterface (ваш третий вариант):

public interface Function<T, R>
                                extends
                                    java.util.function.Function<T, R>,
                                    com.google.common.base.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}

Основным неудобством этого решения является то, что ошибка компилятора eclipse не позволяет использовать Function в качестве целевого типа лямбды .

Если вы действительно хотите сохранить @FunctionalInterface в своей Function , (некрасивым) обходным путем может быть введение промежуточного интерфейса:

public interface AdapterFunction<T, R>
                                      extends
                                          java.util.function.Function<T, R>,
                                          com.google.common.base.Function<T, R> {
    @Override
    default R apply(T input) {
        return null;
    }
}

и пусть ваша Function расширяет эту AdapterFunction :

@FunctionalInterface
public interface Function<T, R>
                                extends
                                    AdapterFunction<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}

В этом случае Function является допустимым целевым типом для eclipse:

Function<String, Object> function = st -> st.toString();




functional-interface