Интерфейс Java

Интерфейс (англ. Interface) в языке программирования Java — это абстрактный тип, набор абстрактных методов. Интерфейсы обычно объявляются с помощью ключевого слова `interface`. Класс наследует абстрактные методы интерфейса, реализуя этот интерфейс.

Интерфейс — это не класс. Написание интерфейса похоже на написание класса, но это разные понятия. Класс описывает свойства и методы объекта. Интерфейс содержит методы, которые класс должен реализовать.

Если класс, реализующий интерфейс, не является абстрактным классом, он должен определить все методы интерфейса.

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

Сходства между интерфейсами и классами:

  • Интерфейс может иметь несколько методов.
  • Файлы интерфейсов сохраняются в файлах с расширением .java, при этом имя файла совпадает с именем интерфейса.
  • Файл байт-кода интерфейса сохраняется в файле с расширением .class.
  • Соответствующий файл байт-кода интерфейса должен находиться в структуре каталогов, соответствующей имени пакета.

Различия между интерфейсами и классами:

  • Интерфейсы нельзя использовать для создания объектов.
  • У интерфейсов нет конструкторов.
  • Все методы в интерфейсе должны быть абстрактными методами. Начиная с Java 8, интерфейсы могут иметь неабстрактные методы, модифицированные ключевым словом `default`.
  • Интерфейсы не могут содержать переменные-члены, за исключением переменных `static` и `final`.
  • Интерфейсы не наследуются классами, а реализуются классами.
  • Интерфейсы поддерживают множественное наследование.

Особенности интерфейсов

  • Каждый метод в интерфейсе также неявно является абстрактным. Методы в интерфейсе неявно определяются какpublic abstract(Только `public abstract`; любой другой модификатор вызовет ошибку.)
  • Интерфейсы могут содержать переменные, но переменные в интерфейсе неявно определяются какpublic static finalпеременные (и только `public`; использование `private` вызовет ошибку компиляции).
  • Методы в интерфейсе не могут быть реализованы в интерфейсе; они могут быть реализованы только классом, который реализует интерфейс.

Разница между абстрактными классами и интерфейсами

  • 1. Методы в абстрактном классе могут иметь тело метода, то есть они могут реализовывать конкретную функциональность метода, а методы в интерфейсе — нет.
  • 2. Переменные-члены в абстрактном классе могут быть различных типов, тогда как переменные-члены в интерфейсе могут быть только типаpublic static final.
  • 3. Интерфейсы не могут содержать статические блоки кода и статические методы (методы, модифицированные `static`), но абстрактные классы могут иметь статические блоки кода и статические методы.
  • 4. Класс может наследовать только один абстрактный класс, но класс может реализовывать несколько интерфейсов.

Примечание: Начиная с JDK 1.8, интерфейсы могут иметь статические методы и тела методов.

Примечание: Начиная с JDK 1.8, интерфейсам разрешено содержать методы с конкретными реализациями, называемые «методами по умолчанию». Методы по умолчанию модифицируются ключевым словом `default`. Для получения дополнительной информации см.Методы по умолчанию в Java 8。

Примечание: Начиная с JDK 1.9, методы разрешено определять как приватные, чтобы некоторый повторно используемый код не раскрывал методы. Для получения дополнительной информации см.Приватные методы интерфейса в Java 9。


Объявление интерфейсов

Синтаксис объявления интерфейса выглядит следующим образом:

[видимость] interfaceимя интерфейса[extendsимена других интерфейсов] { //объявление переменных //абстрактные методы }

Ключевое слово `interface` используется для объявления интерфейса. Ниже приведён простой пример объявления интерфейса.

Код файла NameOfInterface.java:

/*Имя файла: NameOfInterface.java*/ import java.lang.*; //Импорт пакетов public interface NameOfInterface { //Поля любого типа final, static //Абстрактные методы }
Интерфейсы обладают следующими характеристиками:
  • Интерфейсы неявно абстрактны. При объявлении интерфейса нет необходимости использоватьabstractключевое слово.
  • Каждый метод в интерфейсе также неявно абстрактен. При объявлении также не нужноabstractключевое слово.
  • Все методы в интерфейсе являются public.

Пример

Код файла Animal.java:

/*Имя файла: Animal.java*/ interface Animal { public void eat(); public void travel(); }

Реализация интерфейсов

Когда класс реализует интерфейс, класс должен реализовать все методы в интерфейсе. В противном случае класс должен быть объявлен как абстрактный класс.

Класс использует ключевое слово `implements` для реализации интерфейса. В объявлении класса ключевое слово `implements` размещается после объявления `class`.

Синтаксис реализации интерфейса может использовать следующую формулу:

Синтаксис интерфейса:

...implementsимя интерфейса[, другие имена интерфейсов, другие имена интерфейсов..., ...] ...

Пример

Код файла MammalInt.java:

/*Имя файла: MammalInt.java*/ public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); } }

Результат компиляции и выполнения приведенного выше примера выглядит следующим образом:

Mammal eats
Mammal travels

При переопределении методов, объявленных в интерфейсе, необходимо обратить внимание на следующие правила:

  • Когда класс реализует метод интерфейса, он не может выбрасывать обязательное исключение; обязательное исключение может быть выброшено только в интерфейсе или в абстрактном классе, который наследует интерфейс.
  • При переопределении метода класс должен сохранять то же имя метода и должен сохранять тот же или совместимый тип возвращаемого значения.
  • Если класс, реализующий интерфейс, является абстрактным классом, то нет необходимости реализовывать методы интерфейса.

При реализации интерфейса также нужно обратить внимание на некоторые правила:

  • Класс может реализовывать несколько интерфейсов одновременно.
  • Класс может наследовать только один класс, но может реализовывать несколько интерфейсов.
  • Интерфейс может наследовать другой интерфейс, что похоже на наследование между классами.

Наследование интерфейсов

Интерфейс может наследовать другой интерфейс, что похоже на наследование между классами. При наследовании интерфейсов используется ключевое слово `extends`, и дочерний интерфейс наследует методы родительского интерфейса.

Следующий интерфейс Sports наследуется интерфейсами Hockey и Football:

//Имя файла: Sports.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } //Имя файла: Football.java public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } //Имя файла: Hockey.java public interface Hockey extends Sports { public void homeGoalScored(); public void visitingGoalScored(); public void endOfPeriod(int period); public void overtimePeriod(int ot); }

Интерфейс Hockey объявляет четыре метода самостоятельно и наследует два метода из интерфейса Sports. Таким образом, класс, реализующий интерфейс Hockey, должен реализовать шесть методов.

Аналогично, класс, реализующий интерфейс Football, должен реализовать пять методов, два из которых приходят из интерфейса Sports.


Множественное наследование интерфейсов

В Java множественное наследование классов запрещено, но интерфейсы допускают множественное наследование.

При множественном наследовании интерфейсов ключевое слово `extends` нужно использовать только один раз, после чего перечисляются наследуемые интерфейсы. Как показано ниже:

public interface Hockey extends Sports, Event

Приведённый выше фрагмент программы представляет собой корректно определённый субинтерфейс. В отличие от классов, интерфейсы допускают множественное наследование, и Sports и Event могут определять или наследовать одни и те же методы.


Маркерные интерфейсы

Наиболее часто используемый маркерный интерфейс — это интерфейс, не содержащий ни одного метода.

Маркерный интерфейс — это интерфейс без каких-либо методов или свойств. Он лишь указывает, что его класс принадлежит к определённому типу, чтобы другой код мог проверить это и разрешить выполнение определённых действий.

Назначение маркерного интерфейса: простыми словами и образно говоря, он нужен, чтобы поставить на объект метку (штамп), дающую объекту определённые привилегии.

Например: интерфейс java.util.EventListener, который наследуется интерфейсом MouseListener в пакете java.awt.event, определяется следующим образом:

package java.util; public interface EventListener {}

Интерфейс без каких-либо методов называется маркерным интерфейсом. Маркерные интерфейсы в основном используются для следующих двух целей:

  • Создание общего родительского интерфейса:

    Подобно интерфейсу EventListener, который представляет собой Java API, расширяемый десятками других интерфейсов, вы можете использовать интерфейс-маркер, чтобы установить родительский интерфейс для группы интерфейсов. Например: когда интерфейс наследует интерфейс EventListener, виртуальная машина Java (JVM) знает, что этот интерфейс будет использоваться в схеме делегирования событий.

  • Добавить тип данных классу:

    Эта ситуация — исходное назначение интерфейсов-маркеров. Класс, реализующий интерфейс-маркер, не обязан определять какие-либо методы интерфейса (потому что интерфейс-маркер просто не имеет методов), но благодаря полиморфизму класс становится интерфейсным типом.

Другие расширения