Почему есть метод по умолчанию?
Java 8 приближается. Как упоминалось ранее, мы много говорили об этой теме, но выражение Lambdas не единственное изменение правил игры в Java 8.
Предположим, Java 8 была выпущена и содержит Lambda. Теперь вы планируете использовать Lambda.
Список <?> List.faceach (…);
Определение Foreach не может быть найдено в java.util.list или java.util.collection. Обычно это решение для добавления новых методов и реализации в соответствующие интерфейсы в JDK. Однако для выпуска релиза невозможно добавить новый метод к интерфейсу, не влияя на существующую реализацию.
Следовательно, если Lambda используется в Java 8, ее невозможно использовать для библиотеки сбора из -за совместимости вперед.
По вышеуказанным причинам была введена новая концепция. Метод виртуального расширения, который обычно является методом защиты, теперь может быть добавлен в интерфейс, чтобы предоставить реализацию поведения оператора по умолчанию.
Проще говоря, интерфейс Java теперь может реализовать метод. Преимущество метода по умолчанию состоит в том, что он может добавить новый метод по умолчанию в интерфейс без разрушения реализации интерфейса.
На мой взгляд, это не та характеристика Java, которая будет использоваться каждый день, но она может определенно использовать лямбду для естественного использования Lambda.
Самый простой пример
Давайте посмотрим на самый простой пример: интерфейс A, класс Clazz реализует интерфейс A.
Публичный интерфейс a {по умолчанию void foo () {System.out.println ("Cally a.foo ()");} открытый класс класс a {}Код может быть скомпилирован, даже если класс Clazz не реализует метод foo (). Реализация по умолчанию метода foo () представлена в интерфейсе A.
Клиентский код с помощью этого примера:
Clazz clazz = new Clazz ();
Множественное наследство?
Существует общий вопрос: люди задают, когда они сначала услышат новые функции метода по умолчанию », если класс реализует два интерфейса, и оба интерфейса определяют метод по умолчанию с той же подписью. с предыдущими примерами:
Публичный интерфейс a {по умолчанию void foo () {System.out.println ("Calling a.foo ()");Этот код не может составить следующие причины:
Java: класс Clazz от типов A до B до foo () наследует не связанное значение по умолчанию
Чтобы восстановить это, в Clazz мы должны вручную решить метод переписывания конфликта:
Общедоступный класс Clazz реализует a, b {public void foo () {}}} Но что мы должны делать, если хотим позвонить в метод реализации по умолчанию из интерфейса A, вместо реализации нашего собственного метода? Это возможно, процитируйте foo () в A, как показано ниже:
Общедоступный класс Clazz реализует a, b {public void foo () {a.super.foo ();}}} Теперь я не могу быть очень убежден, что мне нравится это окончательное решение. Может быть, это более кратко, чем реализация метода по умолчанию в подписи, как заявлено в первом руке спецификации метода по умолчанию:
Общедоступный класс Clazz Refrents A, B {public void foo () по умолчанию A.foo;}Но это меняет грамматику, не так ли? Если интерфейс A и интерфейс B определяют много методов по умолчанию, которые конфликтуют друг с другом, и я готов использовать метод по умолчанию всего интерфейса A для решения конфликта? В настоящее время я должен разрешить конфликт один за другим, чтобы переписать каждую пару конфликтов. Это может потребовать большой работы и написания большого количества шаблонного кода.
Я оцениваю, что метод разрешения конфликта требует много дискуссий, но кажется, что создатель решает принять неизбежную катастрофу.
Реальный пример
Реальные примеры метода по умолчанию можно найти в раннем пакете JDK8. Вернемся к примеру метода сбора коллекции, мы можем обнаружить, что в интерфейсе java.lang.lang.Terable его реализация по умолчанию заключается в следующем:
@FunctionalInterfacepublic interface iteerable <t> {iterator <t> iterator (); Foreach использует параметр java.util.function.function.
List <?> List = ... list.faceach (system.out :: println);
Метод вызов
Давайте посмотрим, как на самом деле вызывается метод по умолчанию. Если вы не знакомы с этой проблемой, то вам может быть заинтересован в чтении лабораторий Rebel о байтах Java.
С точки зрения клиентского кода метод по умолчанию является лишь общим виртуальным методом. Следовательно, имя должно быть методом виртуального расширения. Следовательно, для простого примера метода по умолчанию в качестве интерфейса клиент -код автоматически вызовет интерфейс в месте, где вызывается метод по умолчанию.
A clazz = clazz ();
Если конфликт метода по умолчанию был разрешен, тогда, когда мы изменяем метод по умолчанию и указываем один из интерфейсов, infokespecial укажет реализацию, какую реализацию интерфейса конкретного вызова.
Общедоступный класс Clazz a, b {public void foo () {a.super.foo (); Ниже приведен выход Javap:
public void foo ();
Как вы видите: Invokespecial инструкции используются для вызова метода интерфейса foo (). С точки зрения Bytecode, это все еще новая вещь, потому что, прежде чем вы сможете вызвать метод, только указывая на класс (родителя) вместо супер, который указывает на интерфейс.
наконец…
Метод по умолчанию является интересным дополнением к языку Java. Основной целью выражения по умолчанию является развитие стандартного интерфейса JDK, и когда мы, наконец, начинаем использовать Lambdas Expression of Java 8, мы предоставляем нам плавный опыт перехода. Кто знает, может быть, мы увидим больше методов по умолчанию в дизайне API в будущем.