Подтвердить что ты не робот

Используют ли методы по умолчанию Java 8 по умолчанию?

Как правило, исходный код Java был передовым. До Java 8, насколько мне известно, и скомпилированные классы, и исходные файлы были совместимы с более поздними версиями JDK/JVM. [Обновление: это неверно, см. Комментарии re 'enum' и т.д. Ниже.] Однако с добавлением методов по умолчанию в Java 8 это больше не имеет места.

Например, библиотека, которую я использовал, имеет реализацию java.util.List, которая включает List<V> sort(). Этот метод возвращает копию содержимого отсортированного списка. Эта библиотека, развернутая как зависимость файла jar, отлично работала в проекте, построенном с использованием JDK 1.8.

Однако позже мне пришлось перекомпилировать библиотеку, используя JDK 1.8 и Я обнаружил, что библиотека больше не компилируется: класс List -implementing со своим собственным методом sort() теперь конфликтует с методом Java 8 java.util.List.sort() по умолчанию. Метод Java 8 sort() по умолчанию сортирует список на месте (возвращает void); мой метод библиотеки sort() - поскольку он возвращает новый отсортированный список - имеет несовместимую подпись.

Итак, мой основной вопрос:

  • Разве JDK 1.8 не вводит форвардную несовместимость для исходного кода Java из-за методов по умолчанию?

также:

  • Является ли это первым таким форвардным несовместимым изменением?
  • Было ли это рассмотрено или обсуждено, когда методы по умолчанию разработаны и реализованы? Документировано ли оно где-нибудь?
  • Было ли (по общему признанию, небольшое) неудобство скидкой и преимуществами?

Ниже приведен пример некоторого кода, который компилируется и запускается под версиями 1.7 и работает под 1,8 - но не компилируется под 1,8:

import java.util.*;

public final class Sort8 {

    public static void main(String[] args) {
        SortableList<String> l = new SortableList<String>(Arrays.asList(args));
        System.out.println("unsorted: "+l);
        SortableList<String> s = l.sort(Collections.reverseOrder());
        System.out.println("sorted  : "+s);
    }

    public static class SortableList<V> extends ArrayList<V> {

        public SortableList() { super(); }
        public SortableList(Collection<? extends V> col) { super(col); }

        public SortableList<V> sort(Comparator<? super V> cmp) {
            SortableList<V> l = new SortableList<V>();
            l.addAll(this);
            Collections.sort(l, cmp);
            return l;
        }

    }

}

Ниже показано, как этот код компилируется (или не выполняется) и выполняется.

> c:\tools\jdk1.7.0_10\bin\javac Sort8.java

> c:\tools\jdk1.7.0_10\bin\java Sort8 this is a test
unsorted: [this, is, a, test]
sorted  : [this, test, is, a]

> c:\tools\jdk1.8.0_05\bin\java Sort8 this is a test
unsorted: [this, is, a, test]
sorted  : [this, test, is, a]

> del Sort8*.class

> c:\tools\jdk1.8.0_05\bin\javac Sort8.java
Sort8.java:46: error: sort(Comparator<? super V>) in SortableList cannot implement sort(Comparator<? super E>) in List
                public SortableList<V> sort(Comparator<? super V> cmp) {
                                       ^
  return type SortableList<V> is not compatible with void
  where V,E are type-variables:
    V extends Object declared in class SortableList
    E extends Object declared in interface List
1 error
4b9b3361

Ответ 1

Разве JDK 1.8 не вводит форвардную несовместимость для исходного кода Java из-за методов по умолчанию?

Любой новый метод в суперклассе или интерфейсе может нарушить совместимость. Способы по умолчанию делают менее вероятным, что изменение интерфейса нарушит совместимость. В том смысле, что методы по умолчанию открывают дверь для добавления методов к интерфейсам, вы можете сказать, что методы по умолчанию могут способствовать некоторой нарушенной совместимости.

Является ли это первым таким передовым несовместимым изменением?

Почти наверняка нет, так как мы были подклассовыми классами из стандартной библиотеки с версии Java 1.0.

Рассматривалось ли это или обсуждалось, когда были разработаны и реализованы методы по умолчанию? Документирован ли он где-нибудь?

Да, это было рассмотрено. См. Brian Goetz Август 2010 г. "Развитие интерфейса через методы" общественного защитника":

  1. Совместимость с исходным кодом

Возможно, что эта схема может привести к несовместимости источника в той мере, в какой модифицируются интерфейсы библиотеки, чтобы вставлять новые методы, которые несовместимы с методами в существующих классах. (Например, если класс имеет метод float-value xyz() и реализует Collection, и мы добавляем метод inty-value xyz() в Collection, существующий класс больше не будет компилироваться.)

Было ли (по общему признанию, небольшое) неудобство скидкой и преимуществами?

До этого, изменение интерфейса, безусловно, нарушит совместимость. Теперь, возможно. Переход от "определенно" к "могу" можно увидеть положительно или отрицательно. С одной стороны, становится возможным добавлять методы к интерфейсам. С другой стороны, он открывает дверь к той несовместимости, которую вы видели, не только с классами, но и с интерфейсами.

Преимущества выше, чем неудобства, однако, как указано в верхней части бумаги Гёца:

  • Описание проблемы

После опубликования невозможно добавить методы к интерфейсу без нарушения существующих реализаций. Чем дольше время, прошедшее с момента публикации библиотеки, тем больше вероятность того, что это ограничение вызовет горе для сопровождающих.

Добавление замыканий на язык Java в JDK 7 повышает нагрузку на устаревшие интерфейсы коллекции; одним из наиболее значительных преимуществ закрытия является то, что он позволяет создавать более мощные библиотеки. Было бы неутешительно добавить языковые функции, которые позволят улучшить библиотеки и в то же время не расширять основные библиотеки, чтобы воспользоваться этой возможностью.

Ответ 2

Разве JDK 1.8 не вводит форвардную несовместимость для исходного кода Java из-за методов по умолчанию?

Да, как вы видели себя.

Является ли это первым таким форвардным несовместимым изменением?

Нет. Ключевое слово Java 5 enum также ломалось, поскольку до этого вы могли иметь переменные с именем, которое больше не будет компилироваться в Java 5 +

Было ли это рассмотрено или обсуждено, когда методы по умолчанию разработаны и внедрены? Документировано ли оно где-нибудь?

Да Описание несовместимости исходного кода Orcale Java 8

Было ли (по общему признанию, небольшое) неудобство дисконтировано в сравнении с преимуществами?

Да

Ответ 3

Мы можем провести параллель с абстрактным классом. Абстрактный класс предназначен для подкласса, чтобы абстрактные методы могли быть реализованы. Сам абстрактный класс содержит конкретные методы, которые ссылаются на абстрактные методы. Абстрактный класс может свободно развиваться путем добавления более конкретных методов; и эта практика может нарушать подклассы.

Поэтому точная проблема, о которой вы говорили, существовала еще до Java8. Проблема гораздо более проявляется в API-интерфейсах Collection, потому что в дикой природе много подклассов.

В то время как ведущей мотивацией метода по умолчанию было добавление некоторых полезных методов в существующие API-интерфейсы Collection без нарушения подклассов, им пришлось проявлять большую самообладание, делая это слишком много, опасаясь разбивать подклассы. Метод по умолчанию добавляется только в том случае, если это абсолютно необходимо. Реальный вопрос здесь в том, почему List.sort считается абсолютно необходимым. Я думаю, что это спорно.

Независимо от того, почему метод по умолчанию был введен в 1-м месте, теперь это отличный инструмент для дизайнеров API, и мы должны относиться к нему так же, как к конкретным методам в абстрактных классах - их нужно тщательно разрабатывать заранее; и новые должны быть введены с большой осторожностью.

Ответ 4

По иронии судьбы были применены методы по умолчанию в интерфейсах, позволяющие существующим библиотекам, использующим эти интерфейсы, не прерываться, а также внедряя новые функциональные возможности в интерфейсах. (обратная совместимость.)

Возможны конфликты типа sort. Что-то нужно заплатить за дополнительную функциональность. В вашем случае также что-то для исследования (следует ли вместо этого использовать новую функциональность?).

Перспективы совместной работы в Java невелики, больше в системе набора текста, которая постоянно расширялась. Сначала с родовыми типами и теперь с выводами типов из функциональных интерфейсов. От версии к версии и от компилятора к компилятору были небольшие отличия.

Ответ 5

Читая эту проблему, я думал о ее решении. Методы по умолчанию решили проблемы обратной совместимости, но проблемы с совместимостью будут существовать.
Я думаю, что вместо расширения существующих классов в таких случаях мы можем иметь интерфейсы, специфичные для нашего приложения, для добавления какого-либо желаемого поведения в наш класс. Мы можем реализовать этот интерфейс и использовать его.