- Синтаксис
- Множественная имплементация
- Расширение интерфейсов
- Статические методы интерфейсов
- Дефолтные методы интерфейсов
- Использование
Интерфейсы в Java представляют собой абстрактные типы, которые определяют набор методов, но не содержат их реализаций. Они позволяют создавать контракты для классов, которые должны реализовать указанные методы, обеспечивая тем самым полиморфизм и возможность работы с различными классами через общий интерфейс.
Синтаксис
// Определение интерфейса
public interface Device { // заголовок
int getRAM(); // методы интерфейса
int getHardDriveMemory();
}
// Реалицация интерфейса классом
public class PC implements Device {
public int getRam() {
System.out.println("PC.getRam");
return 0;
}
public int getHardDriveMemory() {
System.out.println("PC.getHard Drive Memory");
return 0;
}Ы
public int getProcessor() {
System.out.println("PC.getProcessor");
return 0;
}
}
// Пример создания объекта
Device device = new PC();
Множественная имплементация
Один класс в Java может реализовывать несколько интерфейсов одновременно. Если эти интерфейсы содержат методы с одинаковыми именами и параметрами (одинаковой сигнатурой), то класс должен написать реализацию этого метода только один раз
public interface Screen {
int getDpi();
}
public class Laptop implements Screen, Device {
// реализация методов
}
Расширение интерфейсов
В Java интерфейсы могут расширять другие интерфейсы, что позволяет создавать иерархии интерфейсов. Когда один интерфейс расширяет другой, он наследует все методы родительского интерфейса, и класс, реализующий дочерний интерфейс, должен предоставить реализацию для всех методов, включая унаследованные
// Определение интерфейса
public interface Screen extends Device {
int getDpi();
}
// Реалицация интерфейса
public class Laptop implements Screen, Device {
@Override
public int getRam() {
System.out.println("Laptop.getRam");
return 0;
}
@Override
public int getHardDriveMemory() {
System.out.println("Laptop.getHard Drive Memory");
return 0;
}
@Override
public int getDpi() {
System.out.println("Laptop.getDpi");
return 0;
}
}
Статические методы интерфейсов
В Java интерфейсы могут содержать статические переменные и методы, которые можно вызывать без создания экземпляра класса, реализующего этот интерфейс. Статические методы в интерфейсах могут иметь реализацию и используются для выполнения операций, которые не зависят от состояния объектов, реализующих интерфейс. Это позволяет группировать связанные утилитарные функции в одном месте, улучшая организацию кода.
Кроме методов интерфейсы могут содержать и статические переменные, которые автоматически являются константами. Эти переменные не могут изменяться и доступны через имя интерфейса.
public interface Device {
static String INTERFACE_NAME = "Device";
static String getInterfaceName() {
return "Device";
}
int getRam();
int getHardDriveMemory();
}
Дефолтные методы интерфейсов
Дефолтные методы в интерфейсах Java позволяют добавлять реализацию метода непосредственно в интерфейс, используя ключевое слово default
. Это дает возможность интерфейсам эволюционировать, добавляя новые методы без необходимости изменять все классы, которые уже реализуют этот интерфейс. Дефолтные методы обеспечивают обратную совместимость, позволяя существующим классам продолжать работать, даже если интерфейс был обновлён.
public interface Device {
static String INTERFACE_NAME = "Device";
static String getInterfaceName() {
return "Device";
}
int getRam();
int getHardDriveMemory();
default int getSsd () {
System.out.println("Device.getSsd");
return 0;
}
}
// В классе Laptop переопрелим этот метод
public class Laptop implements Screen, Device {
@Override
public int getRam() {
System.out.println("Laptop.getRam");
return 0;
}
@Override
public int getHardDriveMemory() {
System.out.println("Laptop.getHard Drive Memory");
return 0;
}
@Override
public int getDpi() {
System.out.println("Laptop.getDpi");
return 0;
}
@Override
public int getSsd () {
System.out.println("Laptop.getSsd");
return 1;
}
}
Использование
public class Main {
public static void main(String[] args) {
Device pc1 = new PC();
PC pc2 = new PC();
pc1.getRam(); //=> PC.getRam
pc2.getRam(); //=> PC.getRam
pc2.getProcessor(); //=> PC.getProcessor
// Не доступен, так как в интерфейсе нет такого метода
pc1.getProcessor();
Screen Laptop1 = new Laptop();
Device laptop2 = new Laptop();
getAvgRam(List.of(pc1, pc2, laptop1, laptop2));
//=> PC.getRam
//=> PC.getRam
//=> Laptop.getRam
//=> Laptop.getRam
// Вызов статического метода
System.out.println(Device.getInterfaceName()); //=> Device
// Обращение к статической переменной
System.out.println(Device. INTERFACE_NAMED); //=> Device
// Вызов дефолтных методов
// В самом классе Device этот метод не переопределен
// Вызывается дефолтная имплементация
pc1.getSsd(); //=> Device.getSsd
// В классе Laptop метод переопрелен
// Вызывается собственная имплементация
laptop1.getSsd(); //=> Laptop.getSsd
}
public static int getAvgRam(List <Device> devices) {
int result = 0;
for (Device device devices) {
result + device.getRam();
}
return result / devices.size();
}
}
Дополнительные материалы

Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.