У Java 8 і пізніших версіях відповідь на це питання все ще справедлива, але тепер є більш нюансованою.
По-перше, ці твердження з прийнятої відповіді залишаються правильними:
- інтерфейси призначені для конкретизації їх неявної поведінки у контракті (заява про правила поведінки, яким повинні керуватися класи, що реалізують, щоб вважати їх дійсними)
- існує різниця між договором (правилами) та виконанням (програмне кодування правил)
- методи, визначені в інтерфейсі, ОБОВ'ЯЗКОВО ВИНАГИ бути реалізовані (в певний момент)
Отже, який нюанс є новим у Java 8? Якщо говорити про "необов'язкові методи" , зараз підходить будь-яке з наступного:
1. Метод, реалізація якого є контрактним
У "третьому твердженні" йдеться про те, що абстрактні методи інтерфейсу повинні бути впроваджені завжди, і це залишається вірним у Java 8+. Однак, як і в Java Collections Framework, в контракті можна описати деякі абстрактні методи інтерфейсу як "необов'язкові".
У цьому випадку автор, який реалізує інтерфейс, може вирішити не реалізувати метод. Однак компілятор наполягає на реалізації, і тому автор використовує цей код для будь-яких необов'язкових методів, які не потрібні в конкретному класі реалізації:
public SomeReturnType optionalInterfaceMethodA(...) {
throw new UnsupportedOperationException();
}
У Java 7 та більш ранніх версіях це був єдиний тип "необов'язкового методу", тобто метод, який, якщо він не був реалізований, кинув UnsupportedOperationException. Така поведінка обов'язково визначається договором інтерфейсу (наприклад, необов'язкові методи інтерфейсу Java Collections Framework).
2. Метод за замовчуванням, повторна реалізація якого не є обов'язковим
Java 8 представила концепцію методів за замовчуванням . Це методи, реалізація яких може бути і забезпечується самим визначенням інтерфейсу. Зазвичай можна надати методи за замовчуванням лише тоді, коли тіло методу можна записати за допомогою інших методів інтерфейсу (тобто "примітивів") і коли this
може означати "цей об'єкт, клас якого реалізував цей інтерфейс".
Метод за замовчуванням повинен відповідати договору інтерфейсу (як і будь-який інший спосіб реалізації інтерфейсу). Тому конкретизація реалізації методу інтерфейсу в класі реалізації здійснюється на розсуд автора (до тих пір, поки поведінка відповідає його цілям).
У цьому новому середовищі Java Collections Framework можна переписати як:
public interface List<E> {
:
:
default public boolean add(E element) {
throw new UnsupportedOperationException();
}
:
:
}
Таким чином, "необов'язковий" метод add()
має поведінку за замовчуванням закидання UnsupportedOperationException, якщо клас реалізації не надає своєї власної нової поведінки, що саме те, що ви хотіли б, щоб сталося і яке відповідає договору для List. Якщо автор пише клас, який не дозволяє додавати нові елементи до реалізації списку, реалізація не add()
є обов'язковою, оскільки поведінка за замовчуванням саме те, що потрібно.
У цьому випадку вищезазначене "третє твердження" все-таки справедливо, оскільки метод реалізований в самому інтерфейсі.
3. Метод, який повертає Optional
результат
Остаточний новий вид необов'язкового методу - це просто метод, який повертає Optional
. Optional
Клас забезпечує явно більш об'єктно-орієнтована спосіб боротьби з null
результатами.
У плавному стилі програмування, такому, як це часто зустрічається при кодуванні з новим API Java Streams, нульовий результат у будь-якій точці спричиняє збій програми з NullPointerException. Optional
Клас забезпечує механізм для повернення результатів невизначеною коди клієнта таким чином , що дає можливість вільно стиль , не викликаючи клієнтський код аварію.