Интерфейс Java немного похож на класс, за исключением того, что интерфейс может содержать только сигнатуры методов и поля. Интерфейс не может содержать реализацию методов, только подпись(имя, параметры и исключения) метода.
Вы можете использовать их как способ достижения полиморфизма.
Пример интерфейса Java
Вот простой пример интерфейса Java:
public interface MyInterface
Как видите, интерфейс объявляется с использованием ключевого слова. Как и в случае с классами, интерфейс может быть объявлен как общедоступный или пакетный(без модификатора доступа).
Приведенный выше пример содержит одну переменную и один метод. Доступ к переменной можно получить непосредственно из интерфейса, например так:
System.out.println(MyInterface.hello);
Как видите, доступ к переменной очень похож на доступ к статической переменной в классе.
Однако этот метод должен быть реализован некоторым классом, прежде чем вы сможете получить к нему доступ. Следующий раздел объяснит, как это сделать.
Java Interface Tutorial
Реализация интерфейса
Вот класс, который реализует интерфейс MyInterface, показанный выше:
public class MyInterfaceImpl implements MyInterface < public void sayHello() < System.out.println(MyInterface.hello); >>
Обратите внимание, реализует часть MyInterface вышеупомянутого объявления класса. Это сообщает компилятору Java, что класс MyInterfaceImpl реализует интерфейс MyInterface.
Класс, реализующий интерфейс, должен реализовывать все методы, объявленные в нем. Методы должны иметь точно такую же сигнатуру(имя + параметры), как объявлено. Класс не должен реализовывать(объявлять) переменные интерфейса. Только методы.
Экземпляры интерфейса
Как только класс Java реализует интерфейс Java, вы можете использовать экземпляр этого класса в качестве экземпляра. Вот пример:
MyInterface myInterface = new MyInterfaceImpl(); myInterface.sayHello();
Обратите внимание, как объявлена переменная типа интерфейса MyInterface, в то время как созданный объект имеет тип MyInterfaceImpl. Java позволяет это, потому что класс MyInterfaceImpl реализует MyInterface. Затем вы можете ссылаться на экземпляры класса MyInterfaceImpl как на экземпляры MyInterface.
Вы не можете создавать экземпляры интерфейса самостоятельно. Вы должны всегда создавать экземпляр некоторого класса, который реализует интерфейс, и ссылаться на этот экземпляр как на экземпляр интерфейса.
Реализация нескольких интерфейсов
Класс Java может реализовывать несколько интерфейсов. В этом случае класс должен реализовать все методы, объявленные во всех реализованных интерфейсах. Вот пример:
public class MyInterfaceImpl implements MyInterface, MyOtherInterface < public void sayHello() < System.out.println(«Hello»); >public void sayGoodbye() < System.out.println(«Goodbye»); >>
Этот класс реализует два, называемых MyInterface и MyOtherInterface. Вы перечисляете имена для реализации после ключевого слова Implements, разделенных запятой.
Java interface
Если интерфейсы не находятся в тех же пакетах, что и реализующий класс, вам также необходимо импортировать их. Они импортируются с помощью инструкции импорта. Например:
import com.jenkov.package1.MyInterface; import com.jenkov.package2.MyOtherInterface; public class MyInterfaceImpl implements MyInterface, MyOtherInterface
реализованные классом выше:
public interface MyInterface
public interface MyOtherInterface
Как видите, каждый интерфейс содержит один метод. Эти методы реализуются классом MyInterfaceImpl.
Перекрывающиеся подписи метода
Если класс реализует несколько интерфейсов, существует риск, что некоторые могут содержать методы с одинаковой сигнатурой(имя + параметры). Поскольку класс может реализовывать метод только с заданной сигнатурой только один раз, это может привести к проблемам.
Спецификация не дает никакого решения этой проблемы. Вам решать, что делать в этой ситуации.
Какие типы Java могут реализовывать интерфейсы?
Следующие типы могут реализовывать интерфейсы:
- Класс;
- абстрактный класс;
- Вложенный класс;
- Java Enum;
- Динамический Прокси
Переменные интерфейса
Интерфейс может содержать как переменные, так и константы. Однако часто не имеет смысла помещать переменные. В некоторых случаях может иметь смысл определять константы.
Особенно, если эти константы должны использоваться классами, например, в вычислениях, или в качестве параметров для некоторых методов. Я советую вам избегать размещения переменных.
Все переменные в интерфейсе являются открытыми, даже если вы опустите ключевое слово public в объявлении переменной.
Методы интерфейса
Интерфейс может содержать одно или несколько объявлений метода. Как упоминалось ранее, он не может указывать какую-либо реализацию для этих методов. Это зависит от классов, чтобы определить реализацию.
Все методы являются открытыми, даже если вы опустите ключевое слово public в объявлении метода.
Методы интерфейса по умолчанию
До Java 8 интерфейсы не могли содержать реализацию методов, а содержали только сигнатуры методов. Однако это приводит к некоторым проблемам, когда API необходимо добавить метод.
Если API просто добавляет метод, все классы, которые реализуют интерфейс, должны реализовать этот новый метод. Это хорошо, если все реализующие классы расположены в API. Но если некоторые реализующие классы находятся в клиентском коде API(код, который использует API), то этот код нарушается.
Посмотрите на этот интерфейс и представьте, что он является частью, например, API с открытым исходным кодом, который многие приложения используют внутри:
public interface ResourceLoader
Теперь представьте, что проект использует этот API и реализовал ResourceLoader следующим образом:
public class FileLoader implements ResourceLoader < public Resource load(String resourcePath) < // in here is the implementation + // a return statement. >>
Если разработчик API хочет добавить еще один метод в ResourceLoader, то класс FileLoader будет нарушен при обновлении этого проекта до новой версии API.
Чтобы облегчить эту проблему, Java 8 добавила концепцию. Метод интерфейса по умолчанию может содержать реализацию этого метода по умолчанию. Классы, которые реализуют интерфейс, но не содержат реализации по умолчанию, автоматически получат реализацию метода по умолчанию.
Вы помечаете метод как метод по умолчанию, используя ключевое слово. Вот пример:
public interface ResourceLoader < Resource load(String resourcePath); default Resource load(Path resourcePath) < // provide default implementation to load // resource from a Path and return the content // in a Resource object. >>
В этом примере добавляется метод загрузки по умолчанию(Path). В примере не учитывается фактическая реализация(внутри тела метода), потому что это не очень интересно. Важно то, как вы объявляете метод по умолчанию.
Класс может переопределить реализацию метода по умолчанию просто путем явной реализации этого метода, как это обычно делается.
Статические методы интерфейса
Статические методы в Java должны иметь реализацию.
public interface MyInterface < public static void print(String text)< System.out.print(text); >>
Вызов статического метода выглядит и работает так же, как вызов статического метода в классе. Вот пример вызова статического метода print() из вышеуказанного MyInterface:
MyInterface.print(«Hello static method!»);
Статические методы в интерфейсах могут быть полезны, когда у вас есть несколько служебных методов, которые вы хотели бы сделать доступными. Например, Vehicle может иметь статический метод printVehicle(Vehicle v).
Интерфейсы и наследование
Интерфейс Java может наследоваться от другого, как классы могут наследовать от других классов. Вы указываете наследование, используя ключевое слово extends.
public interface MySuperInterface
public interface MySubInterface extends MySuperInterface
MySubInterface расширяет MySuperInterface. Это означает, что MySubInterface наследует все поля и методы от MySuperInterface. Это означает, что если класс реализует MySubInterface, этот класс должен реализовать все методы, определенные как в MySubInterface, так и в MySuperInterface.
Можно определить методы в подинтерфейсе с той же сигнатурой(имя + параметры), что и методы, определенные в суперинтерфейсе, если вы считаете, что это будет лучше в вашем проекте.
В отличие от классов, интерфейсы могут наследоваться от нескольких суперинтерфейсов. Вы указываете это, перечисляя имена всех интерфейсов для наследования, разделенных запятой. Класс, реализующий интерфейс, который наследуется от нескольких, должен реализовывать все методы интерфейса и его суперинтерфейсов.
Вот пример интерфейса Java, который наследуется от нескольких интерфейсов:
public interface MySubInterface extends SuperInterface1, SuperInterface2
Как и при реализации нескольких интерфейсов, не существует правил для того, как вы обрабатываете ситуацию, когда несколько суперинтерфейсов имеют методы с одинаковой сигнатурой(имя + параметры).
Наследование и методы по умолчанию
Методы интерфейса по умолчанию немного усложняют правила наследования интерфейса. Хотя обычно класс может реализовать несколько интерфейсов, даже если интерфейсы содержат методы с одинаковой сигнатурой, это невозможно, если один или несколько из этих методов являются методами по умолчанию. Другими словами, если два интерфейса содержат одну и ту же сигнатуру метода(имя + параметры) и один из интерфейсов объявляет этот метод как метод по умолчанию, класс не может автоматически реализовать оба интерфейса.
Ситуация такая же, если интерфейс расширяет(наследует) несколько интерфейсов, и один или несколько из этих интерфейсов содержат методы с одинаковой сигнатурой, а один из суперинтерфейсов объявляет перекрывающийся метод как метод по умолчанию.
В обеих вышеупомянутых ситуациях компилятор Java требует, чтобы класс, реализующий интерфейс(ы), явно реализовал метод, который вызывает проблему. Таким образом, нет сомнений в том, какую реализацию будет иметь класс. Реализация в классе имеет приоритет над любыми реализациями по умолчанию.
Интерфейсы и полиморфизм
Java-интерфейсы – это способ достижения полиморфизма. Полиморфизм – это концепция, которая требует некоторой практики и мысли, чтобы овладеть ею. По сути, полиморфизм означает, что экземпляр класса(объекта) можно использовать так, как если бы он был разных типов. Здесь тип означает либо класс, либо интерфейс.
Посмотрите на эту простую диаграмму классов:
Приведенные выше классы являются частями модели, представляющей различные типы транспортных средств и водителей, с полями и методами. Это ответственность этих классов – моделировать эти сущности из реальной жизни.
Теперь представьте, что вам нужно иметь возможность хранить эти объекты в базе данных, а также сериализовать их в XML, JSON или другие форматы. Вы хотите, чтобы это было реализовано с использованием одного метода для каждой операции, доступного для каждого объекта Car, Truck или Vehicle. Метод store(), метод serializeToXML() и метод serializeToJSON().
Пожалуйста, забудьте на некоторое время, что реализация этой функциональности как методов непосредственно на объектах может привести к грязной иерархии классов. Просто представьте, что именно так вы хотите выполнить операции.
Где в приведенной выше схеме вы бы поместили эти три метода, чтобы они были доступны для всех классов?
Одним из способов решения этой проблемы было бы создание общего суперкласса для класса Vehicle и Driver, который имеет методы хранения и сериализации. Однако это приведет к концептуальному беспорядку. Иерархия классов больше не будет моделировать транспортные средства и водителей, но также будет привязана к механизмам хранения и сериализации, используемым в вашем приложении.
Лучшим решением было бы создать некоторые интерфейсы с включенными методами хранения и сериализации и позволить классам реализовать эти интерфейсы. Вот примеры таких интерфейсов:
public interface Storable
public interface Serializable
Когда каждый класс реализует эти два интерфейса и их методы, вы можете получить доступ к методам этих интерфейсов, приведя объекты к экземплярам типов интерфейса. Вам не нужно точно знать, к какому классу относится данный объект, если вы знаете, какой интерфейс он реализует.
Car car = new Car(); Storable storable =(Storable) car; storable.store(); Serializable serializable =(Serializable) car; serializable.serializeToXML(new FileWriter(«car.xml»)); serializable.serializeToJSON(new FileWriter(«car.json»));
Как вы уже, наверное, можете себе представить, интерфейсы предоставляют более понятный способ реализации сквозных функций в классах, чем наследование.
Универсальные интерфейсы
public interface MyProducer()
Этот интерфейс представляет интерфейс, который содержит единственный метод, который называется производством(), который может произвести единственный объект. Так как возвращаемое значение yield() – Object, он может возвращать любой объект Java.
public class CarProducer implements MyProducer < public Object produce() < return new Car(); >>
MyProducer carProducer = new CarProducer(); Car car =(Car) carProducer.produce();
public interface MyProducer
MyProducer myCarProducer = new CarProducer(); Car produce = myCarProducer.produce();
Как вы можете видеть, поскольку универсальный тип для экземпляра CarProducer установлен на Car, больше нет необходимости приводить объект, возвращенный из метода yield(), поскольку в объявлении исходного метода в интерфейсе MyProducer указано, что этот метод возвращает тот же тип, который указан в универсальном типе при использовании.
MyProducer myStringProducer = new CarProducer(); String produce1 = myStringProducer.produce();
MyProducer myCarProducer = new CarProducer(); Car produce = myCarProducer.produce();
Как вы можете видеть, по-прежнему нет необходимости приводить объект, возвращаемый функциейручки(), поскольку реализация CarProducer объявляет, что это экземпляр Car.
Обобщения Java более подробно описаны в моем руководстве по обобщению Java.
Функциональные интерфейсы
С Java 8 была введена новая концепция, называемая функциональными интерфейсами. Короче говоря, функциональный интерфейс – это интерфейс с единственным нереализованным методом(нестандартный, нестатический метод). Я объяснил функциональные интерфейсы в моем учебнике по функциональному интерфейсу Java, который является частью моего учебника по функциональному программированию на Java. ,
Источник: java-blog.ru
28. Java – Интерфейсы
Интерфейс – это ссылочный тип в Java. Он схож с классом. Это совокупность абстрактных методов. Класс реализует интерфейс, таким образом наследуя абстрактные методы интерфейса.
Вместе с абстрактными методами интерфейс в Java может содержать константы, обычные методы, статические методы и вложенные типы. Тела методов существуют только для обычных методов и статических методов.
Далее разберём зачем нужны интерфейсы в Java и для чего используются, разницу абстрактного класса и интерфейса.
Написание интерфейса схоже с написанием класса. Но класс описывает атрибуты и поведения объекта. И интерфейс содержит поведения, которые класс реализует.
Если класс, реализующий интерфейс, не является абстрактным, все методы интерфейса должны быть определены в классе.
Чем похожи класс и интерфейс?
Интерфейс схож с классом следующим образом:
- Интерфейс может содержать любое количество методов.
- Интерфейс записан в файле с расширением .java, и имя интерфейса совпадает с именем файла.
- Байт-код интерфейса находится в .class файле.
- Интерфейсы появляются в пакетах, и их соответствующий файл байт-кода должен быть в структуре каталогов, которая совпадает с именем пакета.
Чем отличается класс от интерфейса?
Однако, интерфейс всё же отличается от класса. Отличие интерфейса от класса в Java:
- Вы не можете создать экземпляр интерфейса.
- В интерфейсе не содержатся конструкторы.
- Все методы в интерфейсе абстрактные.
- Интерфейс не может содержать поля экземпляров. Поля, которые могут появиться в интерфейсе, обязаны быть объявлены и статическими, и final.
- Интерфейс не расширяется классом, он реализуется классом.
- Интерфейс может расширить множество интерфейсов.
Объявление интерфейсов
Ключевое слово interface используется для объявления интерфейса. Вот пример того, как можно создать интерфейс:
Пример 1
/* File name : NameOfInterface.java */ import java.lang.*; // Любое количество запросов импорта public interface NameOfInterface < //создание интерфейса // Любое количество полей final и static // Любое количество объявлений абстрактных методов >
Интерфейсы имеют следующие свойства:
- Интерфейс абстрактный косвенно. Вам не нужно использовать ключевое слово abstract во время объявления интерфейса.
- Каждый метод в интерфейсе косвенно абстрактным, поэтому ключевое слово abstract не нужно.
- Методы в интерфейсе косвенно публичны.
Пример 2
/* File name : Animal.java */ interface Animal
Реализация интерфейса
Когда класс реализует интерфейс, вы можете представить себе, что класс словно подписывает контракт с интерфейсом, соглашаясь совершить конкретные его поведения. Если класс не исполняет все поведения интерфейса, то класс должен объявить себя абстрактным.
Класс использует ключевое слово implements для реализации интерфейса. Ключевое слово implements появляется при объявлении класса в его расширенной части.
Пример
/* File name : MammalInt.java */ public class MammalInt implements Animal < public void eat() < System.out.println(«Млекопитающее кушает»); >public void travel() < System.out.println(«Млекопитающее путешествует»); >public int noOfLegs() < return 0; >public static void main(String args[]) < MammalInt m = new MammalInt(); m.eat(); m.travel(); >>
Млекопитающее кушает Млекопитающее путешествует
При переопределении методов в интерфейсе, нужно следовать некоторым правилам:
- Проверенные исключения не должны быть объявлены по методам реализации, отличным от тех, которые были объявлены методом интерфейса или подклассами тех, которые были объявлены методом интерфейса.
- Подпись метода интерфейса и того же типа или подтипа возврата должна поддерживаться (сохраняться) при переопределении методов.
- Сам класс реализации может быть абстрактным, а если это так, то методы интерфейса не должны быть реализованы.
При реализации интерфейсов есть некоторые правила:
- Класс может реализовать более одного интерфейса за раз.
- Класс может расширить только один класс, но реализовать множество интерфейсов.
- Интерфейс может расширить другой интерфейс таким же образом, как класс расширяет другой класс.
Расширение интерфейсов
Интерфейс может расширять другой интерфейс так же, как класс другой класс. Ключевое слово extends используется для расширения интерфейса, и дочерний интерфейс наследует методы родительского интерфейса.
Приведённый интерфейс Sports расширен интерфейсами Hockey и Football.
Пример
// Filename: Sports.java public interface Sports < public void setHomeTeam(String name); public void setVisitingTeam(String name); >// Filename: Football.java public interface Football extends Sports < public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); >// Filename: Hockey.java public interface Hockey extends Sports
Интерфейс Hockey имеет четыре метода, но он наследует два из Sports; таким образом, класс, который реализует Hockey, должен реализовать все шесть методов. Подобно этому, класс, который реализует Football, должен определить три метода из Football и два метода из Sports.
Расширение множества интерфейсов
Класс в Java может расширить только один родительский класс. Множественное наследование невозможно. Однако интерфейсы не классы, и интерфейс может расширить более чем один родительский интерфейс.
Ключевое слово extends используется лишь раз, а родительские интерфейсы объявляются через запятую.
Например, если интерфейс Hockey расширил и Sports, и Event, то объявление выглядело бы так:
public interface Hockey extends Sports, Event
Интерфейсы тегов
Самое распространённое использование расширения интерфейсов происходит тогда, когда родительский интерфейс не содержит каких-либо методов. Например, интерфейс MouseListener в пакете java.awt.event расширил java.util.EventListener, который определяется так:
package java.util; public interface EventListener <>
Интерфейс без методов в нём называется интерфейсом тегов. Есть две простые дизайнерские цели для интерфейсов тегов:
Создаёт общего родителя – как в случае с интерфейсом EventListener, который расширяется множеством других в Java API, вы можете использовать интерфейс тегов, чтобы создать общего родителя среди группы интерфейсов. Например, когда интерфейс расширяет EventListener, то JVM знает, что этот конкретный интерфейс будет использоваться в сценарии делегирования событий.
Добавляет тип данных в класс – эта ситуация является источником термина «тегирование». Класс, который реализует интерфейс тегов, не должен определять какие-либо методы (т.к. интерфейс не имеет таковых), но класс становится типом интерфейса через полиморфизм.
Оглавление
- 1. Java – Самоучитель для начинающих
- 2. Java – Обзор языка
- 3. Java – Установка и настройка
- 4. Java – Синтаксис
- 5. Java – Классы и объекты
- 6. Java – Конструкторы
- 7. Java – Типы данных и литералы
- 8. Java – Типы переменных
- 9. Java – Модификаторы
- 10. Java – Операторы
- 11. Java – Циклы и операторы цикла
- 11.1. Java – Цикл while
- 11.2. Java – Цикл for
- 11.3. Java – Улучшенный цикл for
- 11.4. Java – Цикл do..while
- 11.5. Java – Оператор break
- 11.6. Java – Оператор continue
- 12. Java – Операторы принятия решений
- 12.1. Java – Оператор if
- 12.2. Java – Оператор if..else
- 12.3. Java – Вложенный оператор if
- 12.4. Java – Оператор switch..case
- 12.5. Java – Условный оператор (? 🙂
- 13. Java – Числа
- 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
- 13.2. Java – Метод compareTo()
- 13.3. Java – Метод equals()
- 13.4. Java – Метод valueOf()
- 13.5. Java – Метод toString()
- 13.6. Java – Метод parseInt()
- 13.7. Java – Метод Math.abs()
- 13.8. Java – Метод Math.ceil()
- 13.9. Java – Метод Math.floor()
- 13.10. Java – Метод Math.rint()
- 13.11. Java – Метод Math.round()
- 13.12. Java – Метод Math.min()
- 13.13. Java – Метод Math.max()
- 13.14. Java – Метод Math.exp()
- 13.15. Java – Метод Math.log()
- 13.16. Java – Метод Math.pow()
- 13.17. Java – Метод Math.sqrt()
- 13.18. Java – Метод Math.sin()
- 13.19. Java – Метод Math.cos()
- 13.20. Java – Метод Math.tan()
- 13.21. Java – Метод Math.asin()
- 13.22. Java – Метод Math.acos()
- 13.23. Java – Метод Math.atan()
- 13.24. Java – Метод Math.atan2()
- 13.25. Java – Метод Math.toDegrees()
- 13.26. Java – Метод Math.toRadians()
- 13.27. Java – Метод Math.random()
- 14. Java – Символы
- 14.1. Java – Метод Character.isLetter()
- 14.2. Java – Метод Character.isDigit()
- 14.3. Java – Метод Character.isWhitespace()
- 14.4. Java – Метод Character.isUpperCase()
- 14.5. Java – Метод Character.isLowerCase()
- 14.6. Java – Метод Character.toUpperCase()
- 14.7. Java – Метод Character.toLowerCase()
- 14.8. Java – Метод Character.toString()
- 15. Java – Строки
- 15.1. Java – Метод charAt()
- 15.2. Java – Метод compareTo()
- 15.3. Java – Метод compareToIgnoreCase()
- 15.4. Java – Метод concat()
- 15.5. Java – Метод contentEquals()
- 15.6. Java – Метод copyValueOf()
- 15.7. Java – Метод endsWith()
- 15.8. Java – Метод equals()
- 15.9. Java – Метод equalsIgnoreCase()
- 15.10. Java – Метод getBytes()
- 15.11. Java – Метод getChars()
- 15.12. Java – Метод hashCode()
- 15.13. Java – Метод indexOf()
- 15.14. Java – Метод intern()
- 15.15. Java – Метод lastIndexOf()
- 15.16. Java – Метод length()
- 15.17. Java – Метод matches()
- 15.18. Java – Метод regionMatches()
- 15.19. Java – Метод replace()
- 15.20. Java – Метод replaceAll()
- 15.21. Java – Метод replaceFirst()
- 15.22. Java – Метод split()
- 15.23. Java – Метод startsWith()
- 15.24. Java – Метод subSequence()
- 15.25. Java – Метод substring()
- 15.26. Java – Метод toCharArray()
- 15.27. Java – Метод toLowerCase()
- 15.28. Java – Метод toString()
- 15.29. Java – Метод toUpperCase()
- 15.30. Java – Метод trim()
- 15.31. Java – Метод valueOf()
- 15.32. Java – Классы StringBuilder и StringBuffer
- 15.32.1. Java – Метод append()
- 15.32.2. Java – Метод reverse()
- 15.32.3. Java – Метод delete()
- 15.32.4. Java – Метод insert()
- 15.32.5. Java – Метод replace()
- 16. Java – Массивы
- 17. Java – Дата и время
- 18. Java – Регулярные выражения
- 19. Java – Методы
- 20. Java – Потоки ввода/вывода, файлы и каталоги
- 20.1. Java – Класс ByteArrayInputStream
- 20.2. Java – Класс DataInputStream
- 20.3. Java – Класс ByteArrayOutputStream
- 20.4. Java – Класс DataOutputStream
- 20.5. Java – Класс File
- 20.6. Java – Класс FileReader
- 20.7. Java – Класс FileWriter
- 21. Java – Исключения
- 21.1. Java – Встроенные исключения
- 22. Java – Вложенные и внутренние классы
- 23. Java – Наследование
- 24. Java – Переопределение
- 25. Java – Полиморфизм
- 26. Java – Абстракция
- 27. Java – Инкапсуляция
- 28. Java – Интерфейсы
- 29. Java – Пакеты
- 30. Java – Структуры данных
- 30.1. Java – Интерфейс Enumeration
- 30.2. Java – Класс BitSet
- 30.3. Java – Класс Vector
- 30.4. Java – Класс Stack
- 30.5. Java – Класс Dictionary
- 30.6. Java – Класс Hashtable
- 30.7. Java – Класс Properties
- 31. Java – Коллекции
- 31.1. Java – Интерфейс Collection
- 31.2. Java – Интерфейс List
- 31.3. Java – Интерфейс Set
- 31.4. Java – Интерфейс SortedSet
- 31.5. Java – Интерфейс Map
- 31.6. Java – Интерфейс Map.Entry
- 31.7. Java – Интерфейс SortedMap
- 31.8. Java – Класс LinkedList
- 31.9. Java – Класс ArrayList
- 31.10. Java – Класс HashSet
- 31.11. Java – Класс LinkedHashSet
- 31.12. Java – Класс TreeSet
- 31.13. Java – Класс HashMap
- 31.14. Java – Класс TreeMap
- 31.15. Java – Класс WeakHashMap
- 31.16. Java – Класс LinkedHashMap
- 31.17. Java – Класс IdentityHashMap
- 31.18. Java – Алгоритмы Collection
- 31.19. Java – Iterator и ListIterator
- 31.20. Java – Comparator
- 32. Java – Дженерики
- 33. Java – Сериализация
- 34. Java – Сеть
- 34.1. Java – Обработка URL
- 35. Java – Отправка Email
- 36. Java – Многопоточность
- 36.1. Java – Синхронизация потоков
- 36.2. Java – Межпоточная связь
- 36.3. Java – Взаимная блокировка потоков
- 36.4. Java – Управление потоками
- 37. Java – Основы работы с апплетами
- 38. Java – Javadoc
Источник: proglang.su
Интерфейс
Интерфейс это конструкция языка Java, в рамках которой принято описывать абстрактные публичные ( abstract public ) методы и статические константы ( final static ).
С помощью интерфейса можно указать, что именно должен выполнять класс его реализующий, но не как это делать. Способ реализации выбирает сам класс. Интерфейсы не способны сохранять данные состояния. Интерфейсы — это один из механизмов реализации принципа полиморфизма «один интерфейс, несколько методов».
Рассмотрим следующую картинку. У нас есть контракт (интерфейс), в котором описано какие действия должна выполнять мышка. Это например, клик по правой клавише и клик по левой. Разные производители мышки (классы), реализующие данный контракт (интерфейс), обязаны спроектировать мышки, у которых будут эти действия. Но как выглядят мышки, какие дополнительные опции будут иметь — все это решает сам производитель.
Интерфейсы, как и классы могут быть объявлены с уровнем доступа public или default .
Переменные интерфейса являются public static final по умолчанию и эти модификаторы необязательны при их объявлении. Например, в следующем примере объявлены переменные RIGHT , LEFT , UP , DOWN без каких-либо модификаторов. Но они будут public static final .
Все методы интерфейса являются public abstract и эти модификаторы тоже необязательны. Объявляемые методы не содержат тел, их объявления завершаются точкой с запятой:
public interface Moveable
Чтобы указать, что данный класс реализует интерфейс, в строке объявления класса указываем ключевое слово implements и имя интерфейса. Класс реализующий интерфейс должен содержать полный набор методов, определенных в этом интерфейсе. Но в каждом классе могут быть определены и свои методы. Например, следующий класс Transport реализует интерфейс Moveable . В нем реализованы методы moveRight() и moveLeft() интерфейса Moveable , и добавлены свои методы stop() , start():
public class Transport implements Moveable < public void moveRight() < System.out.println(«Транспорт поворачивает вправо.»); >public void moveLeft() < System.out.println(«Транспорт поворачивает влево.»); >public void stop() < System.out.println(«Транспорт останавливается.»); >public void start() < System.out.println(«Транспорт стартует.»); >>
Один интерфейс может быть реализован любым количеством классов. Например, в следующей схеме добавлены еще два класса Robot и Device , которые тоже реализуют интерфейс Moveable .
Класс Robot из вышеуказанной схемы:
public class Robot implements Moveable < public void moveRight() < System.out.println(«Робот поворачивает вправо.»); >public void moveLeft() < System.out.println(«Робот поворачивает влево.»); >>
Если класс реализует интерфейс, но не полностью реализует определенные в нем методы, он должен быть объявлен как abstract .
Например, класс Device реализует только один метод интерфейса Moveable , поэтому он абстрактный:
public abstract class Device implements Moveable < public void moveRight() < System.out.println(«Девайс поворачивает вправо.»); >>
Тип интерфейса можно указывать при объявлении переменных, содержащих ссылки на объекты, классы которых реализуют этот интерфейс. Например, в следующем примере переменная moveable имеет тип Moveable , и указывает она на объект Transport . Но на основе интерфейсов нельзя порождать объекты.
Например, в строке Moveable moveable1 = new Moveable() будет ошибка компиляции. При использовании переменной типа интерфейс, доступны только те члены класса, которые определены в этом интерфейсе. Например, нельзя вызвать метод start() , используя переменную moveable . А для переменной transport можно:
public class TransportDemo < public static void main(String[] args) < Moveable moveable = new Transport(); Transport transport = new Transport(); Moveable robot = new Robot(); //Moveable moveable1 = new Moveable(); // moveable.start(); moveable.moveRight(); moveable.moveLeft(); System.out.println(); transport.start(); transport.moveRight(); transport.moveLeft(); transport.stop(); System.out.println(); robot.moveLeft(); robot.moveRight(); >>
Один класс может реализовать любое количество интерфейсов. На следующей схеме показан класс Pickup , который реализует два интерфейса CargoAuto и PassengersAuto :
public interface CargoAuto
public interface PassengersAuto
Для указания того, что класс реализует несколько интерфейсов, после ключевого слова implements через запятую перечисляются нужные интерфейсы. Класс Pickup должен определить все методы реализуемых интерфейсов:
public class Pickup implements CargoAuto, PassengersAuto < public void transportCargo() < System.out.println(«Везу груз»); >public void transportPassengers() < System.out.println(«Везу пассажиров»); >>
2. Внутренние интерфейсы
Интерфейсы объявленные в классах или в других интерфейсах называются внутренние или вложенные. Например, интерфейс NestedIf определен внутри класса A:
public class A < public interface NestedIf < boolean isNotNegative(int x); >>
При обращении к интерфейсу NestedIf требуется указывать имя его внешнего класса — A.NestedIf :
public class B implements A.NestedIf < public boolean isNotNegative(int x) < return x >= 0; > >
public class NestedIfDemo < public static void main(String[] args) < A.NestedIf nif = new B(); if (nif.isNotNegative(10)) < System.out.println(«Число 10 не отрицательное.»); >if (nif.isNotNegative(-12)) < System.out.println(«Этo не будет выведено.»); >> >
3. Расширение интерфейсов
Интерфейс может наследоваться от другого интерфейса через ключевое слово extends .
Один интерфейс, в отличие от классов, может расширять несколько интерфейсов.
Например, интерфейс Football расширяет интерфейсы TVProgram и Sport . Класс FootballImpl , реализующий интерфейс Football , должен переопределить методы всех трех интерфейсов Football , TVProgram и Sport :
public interface Sport
public interface Hockey extends Sport
public interface TVProgram
public interface Football extends Sport, TVProgram
4.
Интерфейсы маркеры
Интерфейсы маркеры — это интерфейсы, у которых не определены ни методы, ни переменные. Реализация этих интерфейсов придает классу определенные свойства. Например, интерфейсы Cloneable и Serializable , отвечающие за клонирование и сохранение объекта в информационном потоке, являются интерфейсами маркерами. Если класс реализует интерфейс Cloneable , это говорит о том, что объекты этого класса могут быть клонированы.
5. Методы по умолчанию в интерфейсах
В JDK 8 в интерфейсы ввели методы по умолчанию — это методы, у которых есть реализация. Другое их название — методы расширения. Классы, реализующие интерфейсы, не обязаны переопределять такие методы, но могут если это необходимо. Методы по умолчанию определяются с ключевым словом default .
Интерфейс SomeInterface объявляет метод по умолчанию defaultMethod() с базовой реализацией:
public interface SomeInterface < default String defaultMethod() < return «Объект типа String по умолчанию»; >>
Класс SomeInterfaceImpl1 , реализующий этот интерфейс, не переопределяет метод defaultMethod() — так можно.
public class SomeInterfaceImpl1 implements SomeInterface
А если класс SomeInterfaceImpl2 не устраивает реализация по умолчанию, он переопределяет этот метод:
Создаем два объекта классов SomeInterfaceImpl1 и SomeInterfaceImpl2 , и вызываем для каждого метод defaultMethod() . Для объекта класса SomeInterfaceImpl1 вызовется метод, реализованный в интерфейсе, а для объекта класса SomeInterfaceImpl2 — его собственная реализация:
public class DefaultMethodDemo < public static void main(String[] args) < SomeInterface obj1 = new SomeInterfaceImpl1(); SomeInterface obj2 = new SomeInterfaceImpl2(); System.out.println(obj1.defaultMethod()); System.out.println(obj2.defaultMethod()); >>
Объект типа String по умолчанию Другая символьная строка
6. Статические методы интерфейса
В версии JDK 8, в интерфейсы добавлена еще одна возможность — определять в нем статические методы.
Статические методы интерфейса, как и класса, можно вызывать независимо от любого объекта. Для вызова статического метода достаточно указать имя интерфейса и через точку имя самого метода.
public interface MyIf < int getNumber(); static int staticMethod() < return 0; >>
public class StaticMethodDemo < public static void main(String[] args) < MyIf obj1 = new MyIfImp(); System.out.println(obj1.getNumber()); System.out.println(MyIf.staticMethod()); >>
Источник: www.examclouds.com