这个答案是基于Brian Goetz在2014年12月发表的这篇论文。这是我能找到的关于这个主题的最新消息。但请注意,这篇论文是一篇“非正式草图”,所以关于你的问题还没有明确的内容。
首先,a 不会是 (Subtyping) 的子类型:List<int>
List<Integer>
最初,似乎也是明智的,这可能是 原始的子类型 。但是,鉴于我们的转换策略,类不能是任何类表示的超类,因为这样就会有一个类型域,而应该是类型。所以不能是原始的子类型。(出于同样的原因,不能是 的子类型。Box<int>
Box
Box
Box<int>
Box<int>
t
Object
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);
这样的重载在专用化端(要生成什么方法)和重载选择端(要调用哪个方法)都会有问题。
建议的解决方案称为“剥离”技术:
考虑类似 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)
removeByIndex
removeByValue
removeByValue(T)
removeByIndex(int)
ListLike
removeByIndex
removeByValue
该技术还支持“按部件实现”技术;可以在泛型层中声明一个抽象的方法,并在值层和参考层中提供具体的实现。如果我们允许层,它也将启用“专业化”技术。T=int
使用这种技术,将保持向后兼容性,并将使用新方法和。removeByValue
removeByIndex