关于泛型类使用通配符时的类型赋值问题

TristenC 2020-11-27 04:39:22

/*
* 已知的知识:
* 假设类G是泛型类,那么对于G<A>与G<B>来说,不管类A与类B是否具有继承关系
* G<A>与G<B>都视作两个彼此独立完全没有任何关系的类型,即G<A>对象与G<B>对象的引用无法互相赋值
* 就像一个Sting类型对象的引用不可能赋值给一个Date类型对象,反之亦然
*
* 但是G<A>对象与G<B>对象的引用都可以赋值给G<?>对象
* 因为G<?>相当于G<A>与G<B>的父类,G<?>甚至可以看作是G<Object>的父类
*
* 问题:
* 以下代码中,前三行是没问题的,引用的赋值操作遵循了上述说法
*
* 可是对于第四行代码来说,我只是多嵌套了一层泛型
* 但是编译报错:Type mismatch: cannot convert from Set<Map.Entry<String,Integer>> to Set<Map.Entry<?,?>>
* 即类型不同无法转换
* 按道理第一层被指明的泛型都是Map.Entry应该编译通过,第二层泛型左边是G<?>的形式,右边是G<A>的形式也符合上述说法
* 为什么会报错呢?
*/
Map<String,Integer> map = new HashMap<>();
Set<Map.Entry<String, Integer>> set1 = map1.entrySet();
Set<?> set2 = set1;

Set<Map.Entry<?,?>> set3 = set1;//此行报错


...全文
173 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
TristenC 2021-08-04
精选
  • 打赏
  • 举报
回复

Set<Map.Entry<?,?>> set3 = set1;//此行报错

从其它渠道找到了一个比较靠谱的说法:
当java编译成class文件时会执行类型擦除
类型擦除之后,对于jvm来说并不知道有Map.Entry的存在
这个定义只是约束你在开发时要注意类型一致

qq_39936465 2021-04-27
  • 打赏
  • 举报
回复
引用 楼主 TristenC 的回复:

/*
 * 已知的知识:
 * 	假设类G是泛型类,那么对于G<A>与G<B>来说,不管类A与类B是否具有继承关系
 * 	G<A>与G<B>都视作两个彼此独立完全没有任何关系的类型,即G<A>对象与G<B>对象的引用无法互相赋值
 * 	就像一个Sting类型对象的引用不可能赋值给一个Date类型对象,反之亦然
 * 	
 * 	但是G<A>对象与G<B>对象的引用都可以赋值给G<?>对象
 * 	因为G<?>相当于G<A>与G<B>的父类,G<?>甚至可以看作是G<Object>的父类
 * 
 * 问题:
 * 	以下代码中,前三行是没问题的,引用的赋值操作遵循了上述说法
 * 	
 * 	可是对于第四行代码来说,我只是多嵌套了一层泛型
 * 	但是编译报错:Type mismatch: cannot convert from Set<Map.Entry<String,Integer>> to Set<Map.Entry<?,?>>
 * 	即类型不同无法转换
 * 	按道理第一层被指明的泛型都是Map.Entry应该编译通过,第二层泛型左边是G<?>的形式,右边是G<A>的形式也符合上述说法
 * 	为什么会报错呢?
 */
Map<String,Integer> map = new HashMap<>();
Set<Map.Entry<String, Integer>> set1 = map1.entrySet();
Set<?> set2 = set1;

Set<Map.Entry<?,?>> set3 = set1;//此行报错
估计Map.Entry 是Map内部的接口方法,所以无法识别泛型,需要实例类实现才行。
立青_ 2021-04-24
  • 打赏
  • 举报
回复
按你多说法就是 G<?>是G<A>的父类,但是List<G<?>>不是List<G<A>>的父类啊
a5156520 2021-04-24
  • 打赏
  • 举报
回复
我猜测是因为Map.Entry 里面的泛型必须使用具体的对象类型把

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧