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

2022-09-03 15:29:46

泛型特化以及值类型是未来JVM的预计特征;链接到瓦尔哈拉项目页面 请点击此处。.

现在,根据我的理解,就可以声明一个:

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

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

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


答案 1

这个答案是基于Brian Goetz在2014年12月发表的这篇论文。这是我能找到的关于这个主题的最新消息。但请注意,这篇论文是一篇“非正式草图”,所以关于你的问题还没有明确的内容。

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

最初,似乎也是明智的,这可能是 原始的子类型 。但是,鉴于我们的转换策略,类不能是任何类表示的超类,因为这样就会有一个类型域,而应该是类型。所以不能是原始的子类型。(出于同样的原因,不能是 的子类型。Box<int>BoxBoxBox<int>Box<int>tObjecttintBox<int>BoxBox<int>Box<Integer>

...

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

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

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

public void remove(int position);
public void remove(T element);

这样的重载在专用化端(要生成什么方法)和重载选择端(要调用哪个方法)都会有问题。

建议的解决方案称为“剥离”技术

考虑类似 List 的类中的重载对:

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

will 的现有用法都涉及引用实例化,因为这些是目前在预专业化世界中允许的唯一实例化。请注意,虽然兼容性要求引用实例化同时具有这两种方法,但它不需要非引用实例化(因为当前不存在任何方法)。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 方法)。对于值实例化,并且被视为抽象的,必须提供,但删除根本不存在。remove(T)remove(int)removeByIndexremoveByValueremoveByValue(T)removeByIndex(int)ListLikeremoveByIndexremoveByValue

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

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


答案 2

推荐