Какова цель ключевого слова по умолчанию в Java?
Интерфейс в Java похож на класс, но тело интерфейс может включать в себя только абстрактные методы и final
(Константы).
Недавно я увидел вопрос, похожий на этот
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
В соответствии с определением интерфейса допускаются только абстрактные методы. Почему это позволяет мне скомпилировать вышеуказанный код? Каково ключевое слово default
?
С другой стороны, когда я пытался писать ниже код, тогда он говорит modifier default not allowed here
default class MyClass{
}
вместо
class MyClass {
}
Может ли кто-нибудь сказать мне цель ключевого слова default
? Разрешено ли это только внутри интерфейса? Чем он отличается от default
(без модификатора доступа)?
Ответы
Ответ 1
Это новая функция Java 8, которая позволяет interface
обеспечить реализацию. Описан на Java 8 JLS-13.5.6. Объявление метода интерфейса, которое читает (частично)
Добавление метода default
или изменение метода от abstract
до default
не нарушает совместимость с ранее существовавшими двоичными файлами, но может вызвать IncompatibleClassChangeError
, если ранее существовавший двоичный код пытается вызвать метод. Эта ошибка возникает, если квалификационный тип T
является подтипом двух интерфейсов, I
и J
, где оба I
и J
объявляют метод default
с той же сигнатурой и результатом и ни I
, ни J
не является дополнительным элементом другого.
Что нового в JDK 8 (частично)
Способы по умолчанию позволяют добавлять новые функциональные возможности в интерфейсы библиотек и обеспечивать двоичную совместимость с кодом, написанным для более старых версий этих интерфейсов.
Ответ 2
Методы по умолчанию были добавлены в Java 8 главным образом для поддержки лямбда-выражений. Дизайнеры (на мой взгляд, умно) решили создать синтаксис лямбда-выражения для создания анонимных реализаций интерфейса. Но данные лямбды могут реализовывать только один метод, они будут ограничены интерфейсами с одним методом, что будет довольно серьезным ограничением. Вместо этого были добавлены методы по умолчанию, позволяющие использовать более сложные интерфейсы.
Если вам нужно какое-то убедительное утверждение о том, что default
был введен из-за лямбд, отметьте, что предложение соломенного оферты Project Lambda Марка Рейнхольда в 2009 году упоминает "методы расширения" как обязательную функцию, добавляемую для поддержки лямбд.
Вот пример, демонстрирующий концепцию:
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
Очень надуманный, я понимаю, но должен показать, как по default
поддерживает лямбды. Поскольку inverse
является значением по умолчанию, оно может быть легко переопределено реализующим классом, если требуется.
Ответ 3
В Java 8 введены новые концепции, называемые методами по умолчанию. Способы по умолчанию - это те методы, которые имеют некоторую реализацию по умолчанию и помогают в развитии интерфейсов без нарушения существующего кода. Давайте посмотрим на пример:
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements SimpleInterface{
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
а выход:
Выполнение некоторых работ в классе
Реализация DoSomeOtherWork в интерфейсе
Ответ 4
Что-то, что было упущено в других ответах, было его ролью в аннотациях. Еще в Java 1.5 ключевое слово по default
появилось как средство для предоставления значения по умолчанию для поля аннотации.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
String value() default "AMD";
}
Это использование было перегружено внедрением Java 8, чтобы можно было определить метод по умолчанию в интерфейсах.
Что-то еще, что было упущено: причина, default class MyClass {}
недопустим, объясняется тем, как объявляются классы вообще. На этом языке нет положения, позволяющего отображать это ключевое слово. Тем не менее, он появляется для объявлений метода интерфейса.
Ответ 5
Новая функция Java 8 (методы по умолчанию) позволяет интерфейсу предоставлять реализацию, когда ее помечено ключевым словом по default
.
Например:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Тест интерфейса использует ключевое слово по умолчанию, которое позволяет интерфейсу предоставлять стандартную реализацию метода без необходимости реализации этих методов в классах, использующих интерфейс.
Обратная совместимость. Представьте, что ваш интерфейс реализован сотнями классов, и этот интерфейс заставит всех пользователей реализовать недавно добавленный метод, хотя он не является существенным для многих других классов, которые реализуют ваш интерфейс.
Факты и ограничения:
1-May только объявляется внутри интерфейса, а не внутри класса или абстрактного класса.
2 - должен обеспечить тело
3 - Это не предполагается публичным или абстрактным, как другие обычные методы, используемые в интерфейсе.
Ответ 6
Очень хорошее объяснение содержится в Учебные пособия Java ™, часть объяснения такова:
Рассмотрим пример, в котором участвуют производители компьютеров с компьютерным управлением, которые публикуют отраслевые интерфейсы, которые описывают, какие методы могут быть использованы для управления их автомобилями. Что делать, если эти управляемые компьютером автопроизводители добавляют новые функции, такие как полет, к своим автомобилям? Этим производителям необходимо будет указать новые методы, позволяющие другим компаниям (таким как производители электронных накладных инструментов) адаптировать свое программное обеспечение к летательным аппаратам. Где эти автопроизводители объявят эти новые методы, связанные с полетом? Если они добавят их в свои исходные интерфейсы, тогда программистам, которые реализовали эти интерфейсы, придется переписать их реализации. Если они добавят их как статические методы, тогда программисты будут рассматривать их как полезные методы, а не как основные, основные методы.
Способы по умолчанию позволяют добавлять новые функциональные возможности в интерфейсы ваших библиотек и обеспечивать двоичную совместимость с кодом, написанным для более старых версий этих интерфейсов.
Ответ 7
Способы по умолчанию позволяют добавлять новые функциональные возможности в интерфейсы ваших приложений. Его также можно использовать для множественного наследования.
В дополнение к методам по умолчанию вы можете определять статические методы в интерфейсах. Это облегчает вам организацию вспомогательных методов
Ответ 8
Методы по умолчанию в интерфейсе позволяют нам добавлять новые функциональные возможности, не нарушая старый код.
До Java 8, если в интерфейс был добавлен новый метод, все классы реализации этого интерфейса были обязаны переопределять этот новый метод, даже если они не использовали новые функциональные возможности.
В Java 8 мы можем добавить реализацию по умолчанию для нового метода, используя ключевое слово default
перед реализацией метода.
Даже с анонимными классами или функциональными интерфейсами, если мы видим, что некоторый код можно использовать повторно, и мы не хотим определять одну и ту же логику везде в коде, мы можем написать их реализации по умолчанию и использовать их повторно.
пример
public interface YourInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}