Java 9 或更高版本的预计通用专用化,与列表<int>:.remove() 将如何工作?



通用专业化以及值类型是未来JVM的预测特征;链接到此处的Valhalla项目页面。

现在,据我所知,可以声明一个:

final List<int> myList = new ArrayList<>(); // for instance

但是,除了Collection接口中定义的方法之外,List还定义了另一个.remove()方法,该方法将int作为参数,该参数是要删除的列表中的索引;这就是为什么目前在下面的示例中list的内容:

final List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.remove(2);

[1, 2]而不是[1, 3](选择最具体的重载(。

但是,如果将来我们能够声明一个 List<int> ,我们有一个问题:remove方法的什么重载将被选择?

这个答案是基于Brian Goetz在2014年12月的这篇论文。这是我能找到的关于这个主题的最新信息;但请注意,这篇论文是"非正式草图",因此关于您的问题尚无明确之处。

首先,List<int>不是List<Integer>的子类型(子类型(:

最初,Box<int>可能是原始Box的一个亚型似乎也很明智。但是,考虑到我们的翻译策略,Box类不能是代表Box<int>的任何类的超类,因为Box<int>将有一个类型为Object的字段t,而t应该是类型int。所以Box<int>不能是原始Box的亚型。(出于同样的原因,Box<int>不能是Box<Integer>的子类型。

由于泛型是不变的,因此List<int>不是List<Integer>的子类型也就不足为奇了。这里有点令人惊讶的是,专用类型无法与其原始对应项进行互操作。但是,这不是不合理的限制;不仅不鼓励使用原始类型(引入原始类型只是为了支持从非泛型代码逐渐迁移到泛型代码(,而且仍然可以使用泛型方法编写完全泛型的代码 - 请参阅"泛型方法"。

本文还列出了"迁移挑战",引用原语重载(问题是您的问题(就是其中之一:

今天有效的一些重载在专业化下会成为问题。例如,如果专门使用T=int,这些方法将出现问题:

public void remove(int position);
public void remove(T element);
这种重载

在专用化方面(生成什么方法(和重载选择方面(调用哪种方法(都是有问题的。

建议的解决方案被称为"剥离"技术:

考虑类似列表的类中的重载对:

interface ListLike<T> {
    public void remove(int position);
    public void remove(T element);
}

ListLike的现有用途都将涉及引用实例化,因为这些是目前在专业化前世界中允许的唯一实例化。请注意,虽然兼容性要求引用实例化同时具有这两种方法,但它不需要非引用实例化(因为当前不存在(。

剥离背后的直觉是观察到,虽然我们习惯于将现有ListLike视为泛型类型,但它实际上可能是跨所有实例的泛型类型的联合,以及仅跨引用实例的泛型类型。

如果我们在后专业化世界中从头开始编写这个类,我们可能会把它写成:

interface ListLike<any T> {
    void removeByIndex(int position);
    void removeByValue(T element);
}

但是,现在这样的更改既不是源代码兼容的,也不是二进制兼容的。但是,剥离允许我们将这些方法添加到通用层,并在特定于引用的层中实现它们,而无需在专用化中实现它们,从而恢复兼容性:

interface ListLike<any T> {
    // New methods added to the generic layer
    void removeByValue(T element);
    void removeByIndex(int pos);
    layer<ref T> {
        // Abstract methods that exist only in the ref layer
        void remove(int pos);
        void remove(T element);
        // Default implementations of the new generic methods
        default void removeByIndex(int pos) { remove(pos); }
        default void removeByValue(T t) { remove(t); }
    }
}

现在,引用实例化已经remove(T)remove(int)(以及removeByIndexremoveByValue的新方法(,确保兼容性,并且专用化具有removeByValue(T)removeByIndex(int)的无问题重载。ListLike的现有实现将继续编译,因为新方法具有引用专用化的默认实现(它只是桥接到现有的删除方法(。对于值实例化,removeByIndexremoveByValue被视为抽象的,必须提供,但 remove 根本不存在。

这种技术还支持"按部件实现"技术;可以在通用层中声明方法抽象,并在值层和参考层中提供具体的实现。如果我们允许T=int层,它也将启用"专业化"技术。

使用这种技术,将保持向后兼容性,并使用removeByValueremoveByIndex的新方法。

最新更新