- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我使用泛型编写了一些代码,但遇到了以下我无法理解的情况:
我有接口(interface) IpRange 和下面的类:
public class Scope<IpRange<T extends IP>> {
List<IpRange<T>> rangesList;
public List<IpRange<T>> getRangesList() {return rangesList;}
}
现在从一些测试类,如果我写以下内容:
Scope<Ipv4> myScope = new Scope<Ipv4>();
scope.getRangesList().get(0)
我正在获取 IpRange 类型的对象,但是如果我使用原始类型并执行此操作:
Scope myScope = new Scope();
scope.getRangesList().get(0)
我正在获取 Object,但我无法使用 ipRange 方法,除非我明确地将其转换为 Range。
如果是 List<T>
我明白了,因为我使用了原始类型,编译器无法知道列表项的实际类型是什么,但在这种情况下,它将始终是 IpRange 类型,所以为什么我没有得到 Object?
问题是,当我创建范围时,我不一定知道实际的范围类型。考虑这个构造函数: public Scope(String rangeStringList);据我所知,该字符串可能是“16.59.60.80”或“fe80::10d9:159:f:fffa%”。但我所知道的是,我将一些 IpRange 对象传递给了编译器,我希望能够使用这个接口(interface),无论它是 ipv4 还是 ipv6。而且由于编译器可以确定这是 ipRange 即使我使用行类型,我想知道为什么 java 选择这样做
最佳答案
人们指出,在使用原始类型时,所有泛型类型信息都被剥离,并暗示这是为了向后兼容。我想如果没有解释这可能不会令人满意,所以我将尝试解释像您这样的代码如何遇到这样的问题。
首先,假设您在那里编写的代码是旧库的一部分,并且您正在通过添加泛型来升级库。也许它是一个流行的库,很多人都使用过旧代码。
有人可能已经使用您库中的类完成了类似的事情:
private void someMethod(Scope scope, Object object) {
scope.getRangesList().add(object);
}
现在,看看这个我们知道 Object 可能不是 IpRange 类型,但这是一个私有(private)方法,所以让我们假设类型检查是由任何调用 someMethod 的方法有效执行的。这可能不是好的代码,但如果没有泛型,它确实可以编译并且可能工作得很好。
想象一下,编写此代码的人升级到您的库的新版本以获得一些新功能或未实现的错误修复,除此之外,他们现在还可以使用您的泛型类获得更多类型安全性。不过,他们可能不想使用它,因为有太多遗留问题,例如使用原始类型提取的上述代码。
您的有效建议是,即使“作用域”是原始类型,从 getRangesList() 返回的列表必须始终是类型 List
如果是这种情况,上面将对象添加到列表的遗留代码将不再编译而不被编辑。这是在不忽略原始类型的所有可用泛型类型信息的情况下打破向后兼容性的一种方式。
关于java - 泛型和原始类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13501444/
我是一名优秀的程序员,十分优秀!