generics和原始类型

我使用generics编写了一些代码,我遇到了以下我无法理解的情况:

我有接口IpRange,以及以下类:

public class Scope<IpRange> { List<IpRange> rangesList; public List<IpRange> getRangesList() {return rangesList;} } 

现在来自一些测试类,如果我写下面的内容:

 Scope myScope = new Scope(); scope.getRangesList().get(0) 

我得到IpRange类型的对象,但如果我使用原始类型并执行此操作:

 Scope myScope = new Scope(); scope.getRangesList().get(0) 

我得到了Object,我不能使用ipRange方法,除非我明确地将它转换为Range。

如果它本来是List我得到它,因为我使用原始类型编译器无法知道列表项的实际类型是什么,但在这种情况下它将始终是IpRange类型,所以为什么我’我没有得到对象?

问题在于,当我创建示波器时,我不一定知道实际的范围类型。 考虑这个构造函数:public Sc​​ope(String rangeStringList); 据我所知,字符串可以是“16.59.60.80”或“fe80 :: 10d9:159:f:fffa%”。 但我所知道的是,我将一些IpRange对象传递给编译器,我希望能够使用此接口,无论是ipv4还是ipv6。 而且由于即使我使用了行类型,编译器也可以确定这是ipRange,我想知道为什么java选择这样做

人们已经指出在使用原始类型时会剥离所有generics类型信息,并暗示这与向后兼容性有关。 我想如果没有解释,这可能不会令人满意,所以我将尝试解释像你这样的代码可能会遇到这样的问题。

首先,想象一下您编写的代码是旧库的一部分,并且您正在通过添加generics来升级库。 也许这是一个受欢迎的图书馆,很多人都使用旧代码。

有人可能使用你库中的类做了类似的事情:

 private void someMethod(Scope scope, Object object) { scope.getRangesList().add(object); } 

现在,看看这个我们知道Object可能不是IpRange类型,但这是一个私有方法,所以让我们假设类型检查是通过调用someMethod的任何方法有效地执行的。 这可能不是很好的代码,但没有generics它会编译,它可能工作得很好。

想象一下,写这篇文章的人升级到你的库的新版本以获得一些新function或未实现的bug修复,以及他们现在可以使用你的generics类访问更多类型的安全性。 但是,他们可能不想使用它,过多的遗留问题就像上面使用原始类型的代码一样。

你有效地建议的是,即使’scope’是一个原始类型,从getRangesList()返回的List必须始终是List >,所以编译器应该注意到这一点。

如果是这种情况,那么上面添加一个Object到列表中的遗留代码将不再编译而不进行编译。 这是向后兼容性的一种方式,在不忽略原始类型的所有可用generics类型信息的情况下。

是的,如果使用原始类型,则所有generics都在该方法的其余部分中“关闭”,并且所有generics类型都将变为原始类型,即使它们不会受原始类型的缺失generics参数的影响。

如果使用原始类型,则从类中剥离所有generics类型信息,包括在实例上调用的静态方法。

这样做的原因是为了向后兼容java 1.4。