Поиск по сайту:

Изменения интерфейса Java 8 — статический метод, метод по умолчанию


Изменения интерфейса Java 8 включают статические методы и методы по умолчанию в интерфейсах. До Java 8 в интерфейсах могли быть только объявления методов. Но с Java 8 у нас могут быть методы по умолчанию и статические методы в интерфейсах.

Интерфейс Java 8

Метод интерфейса Java по умолчанию

Для создания метода по умолчанию в интерфейсе java нам нужно использовать ключевое слово \default с сигнатурой метода. Например,

package com.journaldev.java8.defaultmethod;

public interface Interface1 {

	void method1(String str);
	
	default void log(String str){
		System.out.println("I1 logging::"+str);
	}
}

Обратите внимание, что log(String str) является методом по умолчанию в Interface1. Теперь, когда класс будет реализовывать Interface1, не обязательно предоставлять реализацию для методов интерфейса по умолчанию. Эта функция поможет нам в расширении интерфейсов дополнительными методами, все, что нам нужно, это предоставить реализацию по умолчанию. Допустим, у нас есть другой интерфейс со следующими методами:

package com.journaldev.java8.defaultmethod;

public interface Interface2 {

	void method2();
	
	default void log(String str){
		System.out.println("I2 logging::"+str);
	}

}

Мы знаем, что Java не позволяет нам расширять несколько классов, потому что это приведет к «алмазной проблеме», когда компилятор не может решить, какой метод суперкласса использовать. С методами по умолчанию алмазная проблема возникнет и для интерфейсов. Потому что, если класс реализует как Interface1, так и Interface2 и не реализует общий метод по умолчанию, компилятор не может решить, какой из них выбрать. Расширение нескольких интерфейсов является неотъемлемой частью часть Java, вы найдете его в основных классах Java, а также в большинстве корпоративных приложений и фреймворков. Поэтому, чтобы убедиться, что эта проблема не возникнет в интерфейсах, необходимо обеспечить реализацию для общих методов по умолчанию для интерфейсов. Таким образом, если класс реализует оба вышеперечисленных интерфейса, он должен будет обеспечить реализацию для метода log(), иначе компилятор выдаст ошибку времени компиляции. Простой класс, который реализует оба Interface1 и Интер face2 будет:

package com.journaldev.java8.defaultmethod;

public class MyClass implements Interface1, Interface2 {

	@Override
	public void method2() {
	}

	@Override
	public void method1(String str) {
	}

	@Override
	public void log(String str){
		System.out.println("MyClass logging::"+str);
		Interface1.print("abc");
	}
}

Важные моменты о методах интерфейса Java по умолчанию:

  1. Методы интерфейса Java по умолчанию помогут нам расширить интерфейсы, не опасаясь нарушить классы реализации.
  2. Методы интерфейса Java по умолчанию сводят различия между интерфейсами и абстрактными классами.
  3. Методы интерфейса Java 8 по умолчанию помогут нам избежать служебных классов, например, все методы класса Collections могут быть предоставлены в самих интерфейсах.
  4. Методы интерфейса Java по умолчанию помогут нам удалить базовые классы реализации, мы можем предоставить реализацию по умолчанию, а классы реализации могут выбрать, какой из них переопределить.
  5. Одной из основных причин введения методов по умолчанию в интерфейсы является улучшение API коллекций в Java 8 для поддержки лямбда-выражений.
  6. Если какой-либо класс в иерархии имеет метод с такой же сигнатурой, то методы по умолчанию становятся неактуальными. Метод по умолчанию не может переопределить метод из java.lang.Object. Причина очень проста, потому что Object является базовым классом для всех классов Java. Таким образом, даже если у нас есть методы класса Object, определенные как методы по умолчанию в интерфейсах, это будет бесполезно, потому что метод класса Object будет использоваться всегда. Вот почему, чтобы избежать путаницы, у нас не может быть методов по умолчанию, которые переопределяют методы класса Object.
  7. Методы интерфейса Java по умолчанию также называются методами Защитника или методами виртуального расширения.

Статический метод интерфейса Java

Статический метод интерфейса Java аналогичен методу по умолчанию, за исключением того, что мы не можем переопределить их в классах реализации. Эта функция помогает нам избежать нежелательных результатов в случае плохой реализации в классах реализации. Давайте рассмотрим это на простом примере.

package com.journaldev.java8.staticmethod;

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() с плохой реализацией.

package com.journaldev.java8.staticmethod;

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

Interface Null Check
Impl Null Check

Если мы сделаем метод интерфейса статическим по умолчанию, мы получим следующий вывод.

Impl Null Check
MyData Print::
Impl Null Check

Статический метод интерфейса Java виден только методам интерфейса, если мы удалим метод isNull() из класса MyDataImpl, мы не сможем использовать его для MyDataImpl объект. Однако, как и другие статические методы, мы можем использовать статические методы интерфейса, используя имя класса. Например, допустимым утверждением будет:

boolean result = MyData.isNull("abc");

Важные моменты о статическом методе интерфейса Java:

  1. Статический метод интерфейса Java является частью интерфейса, мы не можем использовать его для объектов класса реализации.
  2. Статические методы интерфейса Java хороши для предоставления служебных методов, например проверки на нуль, сортировки коллекций и т. д.
  3. Статический метод интерфейса Java помогает нам обеспечить безопасность, не позволяя классам реализации переопределять их.
  4. Мы не можем определить статический метод интерфейса для методов класса Object, мы получим ошибку компилятора: «Этот статический метод не может скрыть метод экземпляра от Object». Это потому, что это не разрешено в java, поскольку Object является базовым класс для всех классов, и у нас не может быть одного статического метода уровня класса и другого метода экземпляра с одинаковой сигнатурой.
  5. Мы можем использовать статические методы интерфейса Java, чтобы удалить служебные классы, такие как коллекции, и переместить все его статические методы в соответствующий интерфейс, который будет легко найти и использовать.

Функциональные интерфейсы Java

Прежде чем завершить статью, я хотел бы дать краткое введение в функциональные интерфейсы. Интерфейс только с одним абстрактным методом называется функциональным интерфейсом. Новая аннотация @FunctionalInterface позволяет избежать случайного добавления абстрактных методов в функциональные интерфейсы. Это необязательно, но это хорошая практика. Функциональные интерфейсы — долгожданная и востребованная функция Java 8, поскольку она позволяет нам использовать лямбда-выражения для их создания. Добавлен новый пакет java.util.function с набором функциональных интерфейсов для предоставления целевых типов для лямбда-выражений и ссылок на методы. Мы рассмотрим функциональные интерфейсы и лямбда-выражения в следующих постах.