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


В интерфейсе коллекции я нашел метод с именем 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 ключевое слово и как оно работает?

3 87

3 ответа:

Java 8 вводит "метод по умолчанию" или (методы защитника) новую функцию, которая позволяет разработчику добавлять новые методы к интерфейсам, не нарушая существующую реализацию этого интерфейса. Это обеспечивает гибкость, позволяющую интерфейсу определять реализацию, которая будет использоваться по умолчанию в ситуации, когда конкретный класс не может обеспечить реализацию для этого метода.

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 вместо реализации нашей собственной.

можно ссылаться на#foo () следующим образом:

public class Clazz implements A, B {
    public void foo(){
       A.super.foo();
    }
}

эти методы называются методами по умолчанию. метод по умолчанию или способ защитник один из новые возможности в 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

Полезные Ссылки:

Я сделал немного исследования, и я нашел следующее. Надеюсь, это поможет.

существующие проблемы

обычные интерфейсные методы, объявленные как абстрактные и должны быть определены в классе, который реализует интерфейс. Это "обременяет" разработчика класса ответственностью за реализацию каждого объявленного метода. Что еще более важно, это также означает, что расширение интерфейса невозможно после "публикации". В противном случае все исполнители имели бы адаптировать их реализацию, нарушая обратную исходную и бинарную совместимость.

решение, принятое в Java 8

чтобы справиться с этими проблемами, одной из новых функций JDK 8 является возможность расширения существующих интерфейсов с помощью методов по умолчанию. методы по умолчанию не только объявлены, но и определены в интерфейсе.

важные моменты, чтобы отметить

  1. реализаторы смогут выберите не реализовывать методы по умолчанию в реализованный класс.
  2. разработчики все еще могут переопределить значение по умолчанию методы, такие как обычные методы класса non-final, могут быть переопределены в подклассы.
  3. абстрактные классы могут даже (re)объявлять методы по умолчанию как абстрактный, заставляя подклассы переопределять метод (иногда называется "re-abstraction").