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

Java 8: Spliterator, Iterator, Collection и "стандартные" реализации в интерфейсах (Дублирующие методы с именем spliterator)

У вас есть интересная ситуация после выпуска Java 1.8.0_25 в дебрях... Я считаю, что корень моей проблемы связан прежде всего с новыми (до 1.8) функциями реализаций по умолчанию в интерфейсах.

В настоящее время приложение, на котором я работаю, ориентировано на 1,7, что до сих пор работает хорошо. Пока пользователи не начнут обновляться до 1,8. Теперь, когда наши пользователи начали обновляться до 1,8, наша рука вынуждена несколько перейти к поддержке 1.8.

Мы устранили большинство проблем (главным образом, связанных с изменениями пакетов JavaFX между 1.7 и 1.8), но осталась одна неприятная проблема.

В моей мудрости или ее отсутствии я, некоторое время назад, решил создать SortedList <T> который простирается от AbstractList <T> . До сих пор этот класс работал нормально, однако при работе во время выполнения 1.8 я получаю:

Duplicate methods named spliterator with the parameters () and () are inherited 
from the types Collection<T> and Iterable<T>

Это, как мне кажется, вызвано реализацией по умолчанию в некоторых интерфейсах, которые реализованы AbstractList <T> (мой класс SortedList <T> не реализует никаких дополнительных интерфейсов, кроме Serializable). Реализация Serializable - еще одна проблема для нас, поскольку нам необходимо поддерживать десерилизацию SortedList <T> объектов, там нет пути!).

Я могу избавиться от ошибки, предоставив переопределение реализации spliterator() в моем SortedList <T> класс. Однако, если он построен, он больше не работает в среде Java 1.7. Если я попытаюсь использовать SortedList <T> с 1.7 runtime, я получаю:

Problem:
Error: Unresolved compilation problems:
The import java.util.Spliterator cannot be resolved
Spliterator cannot be resolved to a type

com.xxxx.xxxx.util.SortedList.<init>(SortedList.java:13) 

Эта ошибка довольно очевидна, так как теперь мы переопределили метод spliterator() в SortedList <T> он должен включать java.util.Spliterator, но этого не существует в 1.7.

В идеале мы бы хотели, чтобы наши клиенты не обновляли Java 1.8, если они этого не хотят.

Находится ли здесь наша рука? Нужно ли нам заставить пользователей обновляться до версии 1.8, а также развертывать новую версию для всех пользователей, которые сами обновили до 1.8?

Кто-нибудь знает способ решения этой проблемы?

В более философской заметке, почему интерфейс был поврежден с реализацией:-( Может быть отличной новой функцией, но им действительно следовало избегать делать что-либо, что привело бы к нарушению изменений существующего кода, особенно в чем-то таком как списки/коллекции и т.д.

Любая помощь или предложения относительно этого затруднительного положения были бы весьма полезны.

Приветствия,

Марк

4b9b3361

Ответ 1

Хорошо, так что вы оба (@Хольгер и @assylias) были правильны... Но наша ситуация немного сложнее.

Среда, в которой мы работаем, - это Eclipse 3.8.1, которая не поддерживает Java 8 (и не будет в будущем для моего knowelege). Поэтому мы не можем просто перейти на Java 8 компилятор для устранения проблем.

Наш продукт представляет собой значительное приложение RCP Eclipse. Модернизация нашей среды IDE в настоящее время не является вариантом, так как в этом случае произошли серьезные переделки. Нам нужно будет продолжить по этой причине для разработки в среде Java 1.7.

Если кто-то заинтересован, мы решили проблему:

  • Создание фрагментов (по одной на Java-версию, которая вызывает проблемы, так что три в нашем случае) для нашего основного плагина. Эти фрагменты настроены как фрагменты патча.
  • Добавлены Java FX JAR в фрагменты (это было сделано для решения некоторых проблем с Java FX в более ранней версии и снова для версии 1.8.0_25).
  • Также в фрагментах, в том же пространстве имен, что и основной плагин, мы добавили реализацию класса SortedList. Код идентичен для каждого случая, но фрагмент для Java 8 скомпилирован специально с компилятором Java 8. Переопределение метода spliterator() в конце было необязательным (при компиляции с помощью Java 8 компилятор, он работает нормально и все еще компилируется с помощью компилятора 1.7, поскольку больше нет ссылки на класс Spliterator.)

Это, вероятно, не идеальное решение, но мы будем работать: -).

Спасибо за ваш вклад и предложения, высоко ценятся.

Ответ 2

Весь смысл методов по умолчанию - избегать описанной вами ситуации. Приведенный ниже код компилируется и выполняется, как ожидалось, с Java 7 и 8:

public class SortedList<T> extends AbstractList<T> implements Serializable {
  @Override public T get(int index) { return null; }
  @Override public int size() { return 0; }

  public static void main(String[] args) {
    SortedList<String> s = new SortedList<> ();
    System.out.println(s.size());
  }
}

Ответ 3

попробуйте создать абстрактный класс, который переопределяет spliterator() с предпочтительным определением поведения i.e.

abstract class Java8_AbstractCollection<E> extends AbstractCollection<E> {

    /* (non-Javadoc)
     * @see java.util.Collection#spliterator()
     */
    public Spliterator<E> spliterator() {
        return (Spliterator<E>) super.spliterator();
    }
}