我已经知道 Iterator
包含扩展 ZipEntry
但我不能在没有错误的情况下进行向下转换:
ZipFile zf = new ZipFile("a.zip");
// Type mismatch: cannot convert from Iterator<capture#4-of ? extends ZipEntry> to Iterator<ZipEntry>
Iterator<ZipEntry> it = zf.entries().asIterator();
下载在java中不是错误:
String a = "";
// Works fine
Object b = a;
确切的返回类型是 Iterator<? extends ZipEntry>
但是我不需要原始类型,因为我只使用 ZipEntry
.
如果我投的话,我还是会得到一个警告:
// Type safety: Unchecked cast from Iterator<capture#4-of ? extends ZipEntry> to Iterator<ZipEntry>
Iterator<ZipEntry> it = (Iterator<ZipEntry>)zf.entries().asIterator();
如果我已经知道的话,不加检查的石膏有什么问题 ? extends ZipEntry
? 为什么这样不安全?
2条答案
按热度按时间y3bcpkx11#
java泛型允许程序员在编译时绑定(或限制)类处理的元素类型。不要忘记java泛型在运行时并不存在,它们被删除了(如果您不知道的话,可以在google上搜索“java类型删除”以获取更多细节)。
在您的示例中,调用返回的迭代器
zf.entries().asIterator()
绑定到zipentry的任何子类,但不绑定到zipentry类本身。因此编译器检测到您正在将迭代器绑定到zipentry类,而zipentry类被显式地排除在返回的迭代器可以处理的所有可能类的集合之外。通过编写代码
您同意zipfile类公开的接口,并且Assert迭代器将只返回zipentry的某个子类的示例,而不会返回zipentry类的直接示例。
如果你写信
您允许迭代器同时返回zipentry的示例及其所有子类的示例。
这就是我们之间的区别
Iterator<ZipEntry>
以及Iterator<? extends ZipEntry>
xxe27gdn2#
一
Iterator<? extends ZipEntry>
表示未知类型的迭代器。我们唯一知道的是它是ZipEntry
或者是ZipEntry
. 换句话说,可能是Iterator<ZipEntry>
,Iterator<JarEntry>
,或Iterator<SomeOtherSubclass>
实际上。因为这个,你不能确定
Iterator<? extends ZipEntry>
可以分配给类型的变量Iterator<ZipEntry>
. 当然,如果是的话Iterator<ZipEntry>
,则可以分配它,但也可以Iterator<JarEntry>
,或Iterator<SomeOtherSubclass>
,在这种情况下你不能。Foo<T>
以及Foo<U>
是不相关的类型,即使T
是的一个子类U
. 读一读这篇文章,了解为什么这对你来说是正确的List<T>
以及List<U>
.但在这种情况下,这个论点(来自链接的帖子):
不适用于
Iterator
s、 因为您只能从迭代器中获取内容,而不能添加内容。事实上,您可以在迭代器上执行的所有操作都是安全的,即使您是被允许的Iterator<Animal> animals = dogs;
. 但是,编译器不会自动检查所有操作是否安全。java的工作方式是,当您使用泛型类型时,您可以说“请让我分配”
Iterator<JarEntry>
至Iterator<ZipEntry>
,并且不允许我使用任何不安全的操作”。这样做的语法是:(这称为使用站点差异。)
这种“不允许我使用任何不安全的操作”类型与
asIterator
.自
Iterator
如果没有任何这样的不安全操作,您将获得与常规操作完全相同的接口Iterator<ZipEntry>
.把这个和你在电脑上用的时候比较一下
List
. 你不可能add
有什么事吗List<? extends ZipEntry>
,例如。