通用专业化以及值类型是未来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)
(以及removeByIndex
和removeByValue
的新方法(,确保兼容性,并且专用化具有removeByValue(T)
和removeByIndex(int)
的无问题重载。ListLike
的现有实现将继续编译,因为新方法具有引用专用化的默认实现(它只是桥接到现有的删除方法(。对于值实例化,removeByIndex
和removeByValue
被视为抽象的,必须提供,但 remove 根本不存在。这种技术还支持"按部件实现"技术;可以在通用层中声明方法抽象,并在值层和参考层中提供具体的实现。如果我们允许
T=int
层,它也将启用"专业化"技术。
使用这种技术,将保持向后兼容性,并使用removeByValue
和removeByIndex
的新方法。