【问题标题】:Java 8: Spliterator, Iterator, Collection and "default" implemenations in Interfaces (Duplicate methods named spliterator)Java 8:接口中的 Spliterator、Iterator、Collection 和“默认”实现(名为 spliterator 的重复方法)
【发布时间】:2014-12-16 07:04:54
【问题描述】:

在 Java 1.8.0_25 发布后遇到了一个有趣的情况......我相信我的问题的根源主要与接口中“默认”实现的新(到 1.8)特性有关。

我正在开发的应用程序目前的目标是 1.7,到目前为止它运行良好。直到用户开始更新到 1.8。现在我们的用户已经开始更新到 1.8,我们不得不在某种程度上转向支持 1.8。

我们已经修复了大部分问题(主要与 1.7 和 1.8 之间 JavaFX 包的更改有关),但还有一个令人头疼的问题。

根据我的智慧,或者缺乏智慧,我不久前决定创建一个从 AbstractList 扩展的 SortedList。到目前为止,这个类运行良好,但是在 1.8 运行时运行时,我得到:

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

在我看来,这似乎是由 AbstractList 实现的某些接口中的“默认”实现引起的(我的 SortedList 类没有实现除 Serializable 之外的任何其他接口)。实现 Serializable 对我们来说是另一个问题,因为我们需要支持 SortedList 对象的反序列化,这是没有办法的!)。

我可以通过在我的 SortedList 类中提供 spliterator() 的覆盖实现来消除错误。但是,如果构建了它,它就不再在 Java 1.7 环境中运行。如果我尝试将 SortedList 与 1.7 运行时一起使用,我会得到:

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) 

这个错误非常明显,因为我们现在覆盖了 SortedList 中的 spliterator() 方法,它需要包含 java.util.Spliterator,但 1.7 中不存在。

理想情况下,如果客户不愿意,我们不希望他们更新到 Java 1.8。

我们的手是不是被强制到这里了?我们是否需要强制用户更新到 1.8 并且还向任何自己更新到 1.8 的用户推出新版本?

有人知道解决这个问题的方法吗?

从更哲学的角度来说,为什么接口被实现破坏了:-(。可能是一个漂亮的新功能,但他们确实应该避免做任何会导致对现有代码进行破坏性更改的事情,尤其是在这样的事情上基本的列表/集合等。

任何有关此困境的帮助或建议将不胜感激。

干杯,

标记

【问题讨论】:

标签: interface java-8 backwards-compatibility spliterator


【解决方案1】:

默认方法的重点是避免您描述的情况。下面的代码在 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());
  }
}

【讨论】:

  • 这就是我想要的。可能是上面@Holger 建议的编译器问题。
【解决方案2】:

好的,所以你们两个(@Holger 和@assylias)都是正确的......但是,我们的情况有点复杂。

我们正在使用的环境是 Eclipse 3.8.1,它不支持 Java 8(据我所知,将来也不会支持)。所以我们不能只换成 Java 8 编译器来解决问题。

我们的产品是一个相当大的 Eclipse RCP 应用程序。升级我们的 IDE 目前不是一种选择,因为这会涉及到重大的返工。我们需要继续 为此在Java 1.7环境下开发。

如果有人感兴趣,我们已经解决了这个问题:

  • 为我们的主插件创建片段(每个导致问题的 Java 版本一个,在我们的例子中是三个)。这些片段被配置为补丁片段。
  • 将 Java FX JAR 添加到片段中(这样做是为了解决早期版本和 1.8.0_25 版本中 Java FX 的一些问题)。
  • 同样在片段中,在与主插件相同的命名空间中,我们添加了 SortedList 类的实现。每种情况的代码都是相同的,但 Java 8 的片段是使用 Java 8 编译器专门编译的。最终不需要重写 spliterator() 方法(使用 Java 8 编译时) 编译器,它工作正常,仍然可以使用 1.7 编译器编译,因为不再引用 Spliterator 类)。

这可能不是一个理想的解决方案,但我们认为它会起作用:-)。

感谢您的意见和建议,非常感谢。

【讨论】:

    【解决方案3】:

    尝试创建一个抽象类,用首选的行为定义覆盖 spliterator(),即

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-14
      • 2016-09-16
      • 2018-01-28
      • 1970-01-01
      • 2019-04-02
      • 2014-09-25
      • 2015-12-16
      • 2014-06-06
      相关资源
      最近更新 更多