Должен ли "Сопоставимый <T>" быть "функциональным интерфейсом"?

Определение функционального интерфейса: "Функциональный интерфейс - это интерфейс, который имеет только один абстрактный метод (помимо методов Object) и, таким образом, представляет собой контракт с одной функцией".

Согласно этому определению, Comparable<T> определенно является функциональным интерфейсом.

Определение лямбда-выражения: "Лямбда-выражение похоже на метод: оно предоставляет список формальных параметров, а тело - выражение или блок - выражается в терминах этих параметров".

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

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

Давайте посмотрим на Comparable<T>, предназначен ли этот интерфейс для использования в качестве единой функции? то есть. Был ли он предназначен для создания экземпляров только с этой единственной функцией?

Документация Comparable<T> начинается с "Этот интерфейс налагает полное упорядочение на объекты каждого класса, который его реализует. Это упорядочение называется естественным упорядочением класса, а метод compareTo класса называется его естественным методом сравнения ".

Приведенное выше предложение поясняет, что Comparable<T> не предназначен для использования в качестве отдельной функции, но всегда предназначен для реализации классом, который имеет естественное упорядочение для своих экземпляров, путем добавления этой единственной функции.

Что означало бы, что оно не предназначено для создания с помощью лямбда-выражения?

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

Итак, есть ли способ в языке Java, с помощью которого предотвращается создание лямбда-выражения для Comparable<T>? Может ли разработчик интерфейса решить, что этот интерфейс должен быть реализован классом, а не создан как экземпляр с помощью этого единственного метода с использованием лямбда-выражения?

Просто потому, что у интерфейса есть единственный абстрактный метод, его не следует рассматривать как функциональный интерфейс.

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

@NotFunctional
public interface Comparable<T> { public int compareTo(T t); }

Ответ 1

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

Просто потому, что интерфейс имеет единственный абстрактный метод, его не следует рассматривать как функциональный интерфейс.

Это точно правильно. Наличие единственного абстрактного метода является структурным свойством интерфейса, которое делает его пригодным для реализации с помощью лямбды. Однако то, имеет ли интерфейс смысл или семантически разумно быть реализованным с помощью лямбды, - это отдельная история. Последнее является целью аннотации @FunctionalInterface. Когда он присутствует в интерфейсе, это указывает на намерение, чтобы интерфейс был полезен для реализации с помощью лямбды.

Примечательно, что Comparable интерфейс отсутствует @FunctionalInterface аннотации.

Хотя использование лямбда-выражения в качестве Comparable реализации, вероятно, не имеет смысла, похоже, нет никаких оснований для создания механизма, предотвращающего это. Не похоже, что это будет источником ошибки, что послужит хорошей причиной для разработки такого механизма. Напротив, аннотация @FunctionalInterface предназначена для того, чтобы направлять программистов в правильном направлении, а не запрещать что-то, что возможно неправильно, но не кажется действительно вредным.

Ответ 2

Проблема возникает из-за тонкой разницы между "методом" и "функцией".

Выходное значение функции зависит ТОЛЬКО от аргументов, которые вводятся в эту функцию.

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

То есть любая функция является методом, но не все методы являются функциями.

Например, сравнение метода в интерфейсе Компаратор зависит только от его аргументов. Однако метод compareTo в интерфейсе Comparable зависит от состояния объекта для сравнения, поэтому его необходимо реализовать в классе.

Таким образом, даже Comparable имеет один метод abstarct, семантически он не должен рассматриваться как функциональный интерфейс.

Ответ 3

Хорошо, из обсуждений, насколько полезной информативная аннотация @FunctionalInterface (и я счастлив, что Java 8 не требует ее для лямбда).

Comparable обычно является свойством типа и, следовательно, не является хорошим кандидатом для функционального интерфейса. Это явно описано как естественный порядок и не принимает два этих/этих аргумента. Таким образом, это свойство маловероятно, чтобы какой-либо метод работал на лямбда (аргумент similliar применим почти для всех интерфейсов -able).

Итак, дизайнеры коллекции используют второй интерфейс для этой задачи: Comparator<T>, и для этого реализация лямбда это очень естественная выбор.

Ответ 4

Нет механизма предотвращения наивного использования интерфейса, не предназначенного для функционального интерфейса. добавив дополнительную аннотацию, подобную @NotFunctional, она может быть явно объявлена конструктор интерфейса, что он не должен использоваться как лямбда. И по умолчанию, если аннотация не указана, ее можно считать хорошей, как @Functional, который в настоящее время имеет место.