Разница между классом Abstact и интерфейсом
- Абстрактные классы против интерфейсов в Java 8
- Концептуальная разница:
Методы интерфейса по умолчанию в Java 8
- Что такое метод по умолчанию?
- Ошибка компиляции метода ForEach с использованием метода по умолчанию
- Метод по умолчанию и проблемы неоднозначности множественного наследования
- Важные моменты о методах интерфейса Java по умолчанию:
Статический метод интерфейса Java
- Статический метод интерфейса Java, пример кода, статический метод или метод по умолчанию
- Важные моменты о статическом методе интерфейса Java:
Функциональные интерфейсы Java
Абстрактные классы против интерфейсов в Java 8
Изменения интерфейса Java 8 включают статические методы и методы по умолчанию в интерфейсах. До Java 8 у нас могли быть только объявления методов в интерфейсах. Но из Java 8 у нас могут быть стандартные методы и статические методы в интерфейсах.
После введения метода по умолчанию кажется, что интерфейсы и абстрактные классы совпадают. Тем не менее, они все еще отличаются концепцией в Java 8.
Абстрактный класс может определять конструктор. Они более структурированы и могут иметь связанное с ними состояние. В отличие от этого, метод по умолчанию может быть реализован только в терминах вызова других методов интерфейса, без ссылки на состояние конкретной реализации. Следовательно, оба варианта используются для разных целей, и выбор между ними действительно зависит от контекста сценария.
Концептуальная разница:
Абстрактные классы действительны для скелетных (то есть частичных) реализаций интерфейсов, но не должны существовать без соответствующего интерфейса.
Таким образом, когда абстрактные классы эффективно уменьшаются до малозаметности, скелетные реализации интерфейсов, могут ли методы по умолчанию забрать это? Решительно: нет! Для реализации интерфейсов почти всегда требуются некоторые или все те инструменты построения классов, в которых отсутствуют методы по умолчанию. А если какой-то интерфейс этого не делает, это явно особый случай, который не должен вводить вас в заблуждение.
Методы интерфейса по умолчанию в Java 8
Java 8 представляет новую функцию « Метод по умолчанию » или (методы Defender), которая позволяет разработчику добавлять новые методы в интерфейсы, не нарушая существующую реализацию этих интерфейсов. Это обеспечивает гибкость, позволяющую интерфейсу определять реализацию, которая будет использоваться по умолчанию в ситуации, когда конкретный класс не сможет обеспечить реализацию для этого метода.
Давайте рассмотрим небольшой пример, чтобы понять, как это работает:
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
Следующий класс будет успешно скомпилирован в Java JDK 8,
public class OldInterfaceImpl implements OldInterface {
public void existingMethod() {
// existing implementation is here…
}
}
Если вы создаете экземпляр OldInterfaceImpl:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod();
Методы по умолчанию никогда не являются окончательными, не могут быть синхронизированы и не могут переопределять методы объекта. Они всегда общедоступны, что серьезно ограничивает возможность написания коротких и многократно используемых методов.
Методы по умолчанию могут предоставляться интерфейсу, не влияя на реализацию классов, так как он включает реализацию. Если каждый добавленный метод в Интерфейсе определен с реализацией, то никакой Класс реализации не затронут. Реализующий класс может переопределить реализацию по умолчанию, предоставляемую интерфейсом.
Методы по умолчанию позволяют добавлять новые функциональные возможности к существующим интерфейсам, не нарушая более старую реализацию этих интерфейсов.
Когда мы расширяем интерфейс, который содержит метод по умолчанию, мы можем выполнить следующее,
- Не переопределяет метод по умолчанию и будет наследовать метод по умолчанию.
- Переопределите метод по умолчанию, аналогично другим методам, которые мы переопределяем в подклассе.
- Переопределите метод по умолчанию как абстрактный, что заставляет подкласс переопределять его.
Ошибка компиляции метода ForEach с использованием метода по умолчанию
Для Java 8 коллекции JDK были расширены, а метод forEach добавлен ко всей коллекции (которые работают в сочетании с лямбдами). Обычным способом код выглядит так:
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
Так как каждый из этих результатов реализует класс с ошибками компиляции, метод по умолчанию добавляется с требуемой реализацией, чтобы существующая реализация не изменялась.
Итерируемый интерфейс с методом по умолчанию ниже,
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
Тот же механизм был использован для добавления потока в интерфейс JDK без нарушения реализации классов.
Метод по умолчанию и проблемы неоднозначности множественного наследования
Поскольку Java-класс может реализовывать несколько интерфейсов, и каждый интерфейс может определять метод по умолчанию с одинаковой сигнатурой метода, следовательно, унаследованные методы могут конфликтовать друг с другом.
Рассмотрим ниже пример,
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
Приведенный выше код не будет скомпилирован со следующей ошибкой,
Java: класс Impl наследует несвязанные значения по умолчанию для defaultMethod () от типов InterfaceA и InterfaceB
Чтобы исправить этот класс, нам нужно предоставить реализацию метода по умолчанию:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
Кроме того, если мы хотим вызвать реализацию по умолчанию, предоставляемую любым из суперинтерфейсов, а не нашей собственной реализацией, мы можем сделать это следующим образом:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
Мы можем выбрать любую реализацию по умолчанию или обе в рамках нашего нового метода.
Важные моменты о методах интерфейса Java по умолчанию:
- Методы интерфейса Java по умолчанию помогут нам в расширении интерфейсов, не боясь нарушать классы реализации.
- Методы по умолчанию для интерфейса Java позволяют устранить различия между интерфейсами и абстрактными классами.
- Методы интерфейса Java по умолчанию помогут нам избежать использования вспомогательных классов, например, все методы класса Collections могут быть предоставлены в самих интерфейсах.
- Методы интерфейса Java по умолчанию помогут нам в удалении базовых классов реализации, мы можем предоставить реализацию по умолчанию, и классы реализации могут выбрать, какой из них переопределить.
- Одной из основных причин введения методов по умолчанию в интерфейсах является усовершенствование API коллекций в Java 8 для поддержки лямбда-выражений.
- Если какой-либо класс в иерархии имеет метод с такой же сигнатурой, то методы по умолчанию становятся неактуальными. Метод по умолчанию не может переопределить метод из java.lang.Object. Рассуждения очень просты, потому что Object является базовым классом для всех классов Java. Таким образом, даже если у нас есть методы класса Object, определенные как методы по умолчанию в интерфейсах, это будет бесполезно, потому что метод класса Object всегда будет использоваться. Вот почему во избежание путаницы у нас не может быть методов по умолчанию, которые переопределяют методы класса Object.
- Методы интерфейса Java по умолчанию также называются методами защитника или методами виртуального расширения.
Ссылка на ресурс:
- Интерфейс с методами по умолчанию против абстрактного класса в Java 8
- Абстрактный класс против интерфейса в эпоху JDK 8
- Эволюция интерфейса с помощью виртуальных методов расширения
Статический метод интерфейса Java
Статический метод интерфейса Java, пример кода, статический метод или метод по умолчанию
Статический метод интерфейса Java похож на метод по умолчанию, за исключением того, что мы не можем переопределить его в классах реализации. Эта функция помогает нам избежать нежелательных результатов в случае плохой реализации в классах реализации. Давайте рассмотрим это на простом примере.
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Теперь давайте посмотрим на класс реализации, который имеет метод isNull () с плохой реализацией.
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Обратите внимание, что isNull (String str) - это простой метод класса, он не переопределяет метод интерфейса. Например, если мы добавим аннотацию @Override в метод isNull (), это приведет к ошибке компилятора.
Теперь, когда мы запустим приложение, мы получим следующий вывод.
Проверка интерфейса на ноль
Impl Null Check
Если мы сделаем интерфейсный метод статическим по умолчанию, мы получим следующий вывод.
Impl Null Check
MyData Print ::
Impl Null Check
Статический метод интерфейса Java видим только для методов интерфейса, если мы удалим метод isNull () из класса MyDataImpl, мы не сможем использовать его для объекта MyDataImpl. Однако, как и другие статические методы, мы можем использовать статические методы интерфейса, используя имя класса. Например, допустимым утверждением будет:
boolean result = MyData.isNull("abc");
Важные моменты о статическом методе интерфейса Java:
- Статический метод интерфейса Java является частью интерфейса, мы не можем использовать его для объектов класса реализации.
- Статические методы интерфейса Java хороши для предоставления служебных методов, например проверки нуля, сортировки коллекции и т. Д.
- Статический метод интерфейса Java помогает нам обеспечивать безопасность, не позволяя классам реализации переопределять их.
- Мы не можем определить статический метод интерфейса для методов класса Object, мы получим ошибку компилятора как «Этот статический метод не может скрыть метод экземпляра от Object». Это потому, что это не разрешено в Java, так как Object является базовым классом для всех классов, и у нас не может быть одного статического метода уровня класса и другого метода экземпляра с одинаковой сигнатурой.
- Мы можем использовать статические методы интерфейса Java, чтобы удалить служебные классы, такие как Коллекции, и переместить все его статические методы в соответствующий интерфейс, который было бы легко найти и использовать.
Функциональные интерфейсы Java
Прежде чем завершить пост, я хотел бы дать краткое введение в функциональные интерфейсы. Интерфейс с точно одним абстрактным методом известен как функциональный интерфейс.
Новая аннотация @FunctionalInterface
была введена, чтобы пометить интерфейс как функциональный интерфейс. @FunctionalInterface
Аннотация - это возможность избежать случайного добавления абстрактных методов в функциональные интерфейсы. Это необязательно, но это хорошая практика.
Функциональные интерфейсы являются долгожданной и востребованной функцией Java 8, поскольку она позволяет нам использовать лямбда-выражения для их создания. Добавлен новый пакет java.util.function с набором функциональных интерфейсов для предоставления целевых типов для лямбда-выражений и ссылок на методы. Мы рассмотрим функциональные интерфейсы и лямбда-выражения в следующих статьях.
Расположение ресурса:
- Изменения интерфейса Java 8 - статический метод, метод по умолчанию