13

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

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

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

根据我的智慧,或者缺乏智慧,我不久前决定创建一个从 AbstractList<T> 扩展的 SortedList<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> 对象的反序列化,没有办法解决这个问题!)。

我可以通过在我的 SortedList<T> 类中提供 spliterator() 的覆盖实现来消除错误。但是,如果构建了它,它就不再在 Java 1.7 环境中运行。如果我尝试将 SortedList<T> 与 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<T> 中的 spliterator() 方法,它需要包含 java.util.Spliterator,但在 1.7 中不存在。

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

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

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

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

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

干杯,

标记

4

3 回答 3

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());
  }
}
于 2014-10-21T07:41:35.923 回答
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 类)。

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

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

于 2014-10-22T04:40:16.620 回答
0

尝试使用首选行为定义创建一个覆盖 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();
    }
}
于 2015-09-14T11:35:19.840 回答