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?
Кто-нибудь знает способ решения этой проблемы?
В более философской заметке, почему интерфейс был поврежден с реализацией:-( Может быть отличной новой функцией, но им действительно следовало избегать делать что-либо, что привело бы к нарушению изменений существующего кода, особенно в чем-то таком как списки/коллекции и т.д.
Любая помощь или предложения относительно этого затруднительного положения были бы весьма полезны.
Приветствия,
Марк
Ответы
Ответ 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();
}
}