Что такое "по умолчанию" реализация метода, определенного в интерфейсе?
В интерфейсе коллекции я нашел метод с именем removeIf()
, который содержит его реализацию.
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
Я хочу знать, есть ли способ определить тело метода в интерфейсе?
Каково ключевое слово default
и как оно работает?
Ответы
Ответ 1
С https://dzone.com/articles/interface-default-methods-java
Java 8 представляет новую функцию "Метод по умолчанию" или (методы Defender), которая позволяет разработчику добавлять новые методы в интерфейсы, не нарушая существующую реализацию этих интерфейсов. Это обеспечивает гибкость, позволяющую реализацию определения интерфейса, которая будет использоваться по умолчанию в ситуации, когда конкретный класс не сможет обеспечить реализацию для этого метода.
public interface A {
default void foo(){
System.out.println("Calling A.foo()");
}
}
public class ClassAB implements A {
}
Существует один распространенный вопрос, который люди задают о методах по умолчанию, когда они впервые слышат о новой функции:
Что если класс реализует два интерфейса, и оба этих интерфейса определяют метод по умолчанию с одинаковой сигнатурой?
Пример для иллюстрации этой ситуации:
public interface A {
default void foo(){
System.out.println("Calling A.foo()");
}
}
public interface B {
default void foo(){
System.out.println("Calling B.foo()");
}
}
public class ClassAB implements A, B {
}
Этот код не компилируется со следующим результатом:
java: class Clazz inherits unrelated defaults for foo() from types A and B
Чтобы исправить это, в Clazz нам нужно разрешить это вручную, переопределив конфликтующий метод:
public class Clazz implements A, B {
public void foo(){}
}
Но что если мы хотели бы вызвать реализацию метода foo() по умолчанию из интерфейса A вместо реализации нашей собственной.
К A # foo() можно обратиться следующим образом:
public class Clazz implements A, B {
public void foo(){
A.super.foo();
}
}
Ответ 2
Эти методы называются методами по умолчанию. Метод по умолчанию или метод Defender является одним из недавно добавленных функций в Java 8.
Они будут использоваться, чтобы позволить методу интерфейса предоставлять реализацию, используемую по умолчанию, в случае, если конкретный класс не предоставляет реализацию для этого метода.
Итак, если у вас есть интерфейс с методом по умолчанию:
public interface Hello {
default void sayHello() {
System.out.println("Hello");
}
}
Вполне справедлив следующий класс:
public class HelloImpl implements Hello {
}
Если вы создаете экземпляр HelloImpl
:
Hello hello = new HelloImpl();
hello.sayHello(); // This will invoke the default method in interface
Полезные ссылки:
Ответ 3
Я немного поработал, и нашел следующее. Надеюсь, это поможет.
Существующая проблема
Нормальные методы интерфейса объявляются абстрактными и должны быть определены в классе, реализующем интерфейс. Это "обременяет" класс-исполнителя с ответственностью за выполнение каждого объявленного метода. Что еще более важно, это также означает, что расширение интерфейса невозможно после публикации. В противном случае всем разработчикам пришлось бы адаптировать их реализацию, нарушая исходную и двоичную совместимость.
Решение, принятое на Java 8
Чтобы справиться с этими проблемами, одной из новых возможностей JDK 8 является возможность расширения существующих интерфейсов с использованием методов по умолчанию. Методы по умолчанию не только объявлены, но также определены в интерфейсе.
Важно отметить
- Исполнители могут не использовать методы по умолчанию в
реализующий класс.
- Исполнители могут по-прежнему переопределять стандартные
методы, такие как обычные методы не конечного класса, могут быть переопределены в
подклассы.
- Абстрактные классы могут даже (re) объявлять методы по умолчанию
как абстрактные, вынуждая подклассы переопределять метод (иногда
называемой "повторной абстракцией" ).