2013-08-17 5 views
84

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

см это сообщение о умолчанию http://zeroturnaround.com/rebellabs/java-8-explained-default-methods/ #!/ – emeraldjava

+0

Связанное сообщение https://stackoverflow.com/questions/31578427/what-is-the-purpose-of-the-default-keyword-in-java – Ravi

ответ

141

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(); 
    } 
} 
+14

Спасибо, действительно хорошая экспозиция. Вы ответили на все мои вопросы, прежде чем я имел возможность спросить их. –

+1

Очень хорошее объяснение. Большое спасибо. – user2045474

+0

Почему бы не использовать абстракцию вместо этого? –

48

Эти методы называются методами по умолчанию. метод по умолчанию или Defender метод является одним из newly added features в 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 

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

+0

Итак, это нормально, если класс реализует интерфейс, а не реализовать его метод? Что касается Java7, то я не могу это использовать. –

+2

@AniketThakur. Это недопустимо до Java 8. Эта функция добавляется только в Java 8. Вы можете избежать применения методов * default * в вашем классе реализации. –

+0

Отлично, а затем +1 для ответа :) –

17

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

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

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

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

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

Важные моменты отметить

  1. реализаторы может не реализовывать стандартные методы в реализующего класса.
  2. Реализации могут по-прежнему переопределять стандартные методы , например, обычные методы не конечного класса могут быть переопределены в подклассах .
  3. Абстрактные классы могут даже (re) объявлять методы по умолчанию как абстрактные, заставляя подклассы переопределять метод (иногда называемый «повторная абстракция»).
Смежные вопросы