Что такое "по умолчанию" реализация метода, определенного в интерфейсе?

В интерфейсе коллекции я нашел метод с именем 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) объявлять методы по умолчанию как абстрактные, вынуждая подклассы переопределять метод (иногда называемой "повторной абстракцией" ).