请教一下java泛型中方法自身的泛型变量赋值问题:static void fill(List list,T obj)

tkk13 2016-07-10 03:24:53
刚学到java的泛型,有点糊涂了,想向大家请教一下泛型变量T的用法
在Collections中有方法static <T> void fill(List<? super T> list,T obj) ,
问:T作为一个变量为什么不需要被提前赋值?
像一般的用法 <T> void method(ArrayList<T> a1)我能理解为T是在传入实参比如ArrayList<String> a1然后将a1作为实参传入method的时候形参T被赋值为String.
但是上面这种在形参中对T进行超类的方法,它的T为什么没赋值直接用?类似的还有Collections的max方法,
<T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
这个方法中更纠结了
T既在前面对T进行限定,又在形参列表中对T进行运用.这是什么情况.其中的运行机制是怎样的?
...全文
813 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
解开者 2016-07-13
  • 打赏
  • 举报
回复
以max方法来说,假设有ABC三个类,B继承A,C继承B,有三个List,abc的参数类型分别是ABC 则有以下现象:如果A实现了Comparable接口,那么用abc调用max能通过编译;如果B实现了Comparable接口,那么用bc调用max能通过编译;如果C实现了Comparable接口,那么用c调用max能通过编译;编译错误的报错如下
Bound mismatch: The generic method f(Collection<? extends T>) of type CollectionsTest is not applicable for the arguments (List<A>). The inferred type A is not a valid substitute for the bounded parameter <T extends Object & Comparable<? super T>>
因为? extends T要求T以是coll参数类型的父类为条件进行推断,<T extends Object & Comparable<? super T>>又要求T必须实现Comparable接口,故产生上述现象。同理,若令B实现Comparable<C>,则用b调用max也会编译错误。 至于参数类型T本身,倒不是必须要对应某个实际类型,它只是为了表达推断关系的一个代位符。 Eclipse等IDE,鼠标悬停在泛型方法调用上时,能看到类型推断的结果。 最次,在调用泛型方法时,是可以手动指定参数类型的,比如以下代码:
		Arrays.asList(1.1, 1);
		List<Number> a = Arrays.asList(1.1, 1);
		List<Number> b = Arrays.<Number>asList(1.1, 1);
第一行编译警告:
Type safety: A generic array of Number&Comparable<?> is created for a varargs parameter
意思就是存在两个可能的推断类型Number和Comparable<?>。 所以第二行编译错误:
Type mismatch: cannot convert from List<Number&Comparable<?>> to List<Number>
而第三行可以通过编译,这也是调用泛型方法指定参数类型的语法。
tkk13 2016-07-13
  • 打赏
  • 举报
回复
引用 3 楼 wpsama 的回复:
[quote=引用 2 楼 tkk13 的回复:] [quote=引用 1 楼 wpsama 的回复:] void show(Stirng name){} name是一个变量,变量值可以是张三,也可以是李四 ArrayList<String>这个你理解吗?就是说这个ArrayList集合里存的元素只能是String T你一开始可以理解为Object ArrayList<T>就是说这个ArrayList里存的元素可以是任何类型,T的值可以是String,也可以是Integer <T> void method(ArrayList<T> a1) 最前面的<T>没有实际意义,是在定义泛型方法时的一个固定格式,固定标记 T不需要提前定义,你在调用这个方法的时候,你规定是什么,就是什么 比如你这个方法static <T> void fill(List<? super T> list,T obj) , 调用时可以这样写:Collections.fill(List<Animal>,Cat cat); T你定义为猫,? super T,那么?可以是猫科动物,动物,生物都行,只要是猫的父类
但是这个解释没办法解释我给的第二个例子,第二个例子里面参数部分没有T本体,只有Collection<? extends T> coll 啊[/quote] 没有问题啊? T max(Collection<? extends T> coll) max函数需要传入一个Collection<猫 extends 动物>;函数的返回值是一个动物[/quote] 我的意思是,T的值没有被设定,那么我也可以说Collection<猫 extends 生物> 那么函数返回值也可以是生物了 甚至Collection<猫 extends 物质>,不是也可以吗.输入了一个猫,只要T是猫的父类就可以了,那么T的类型怎么确定呢?
公子寻欢 2016-07-12
  • 打赏
  • 举报
回复
引用 2 楼 tkk13 的回复:
[quote=引用 1 楼 wpsama 的回复:] void show(Stirng name){} name是一个变量,变量值可以是张三,也可以是李四 ArrayList<String>这个你理解吗?就是说这个ArrayList集合里存的元素只能是String T你一开始可以理解为Object ArrayList<T>就是说这个ArrayList里存的元素可以是任何类型,T的值可以是String,也可以是Integer <T> void method(ArrayList<T> a1) 最前面的<T>没有实际意义,是在定义泛型方法时的一个固定格式,固定标记 T不需要提前定义,你在调用这个方法的时候,你规定是什么,就是什么 比如你这个方法static <T> void fill(List<? super T> list,T obj) , 调用时可以这样写:Collections.fill(List<Animal>,Cat cat); T你定义为猫,? super T,那么?可以是猫科动物,动物,生物都行,只要是猫的父类
但是这个解释没办法解释我给的第二个例子,第二个例子里面参数部分没有T本体,只有Collection<? extends T> coll 啊[/quote] 没有问题啊? T max(Collection<? extends T> coll) max函数需要传入一个Collection<猫 extends 动物>;函数的返回值是一个动物
tkk13 2016-07-12
  • 打赏
  • 举报
回复
引用 1 楼 wpsama 的回复:
void show(Stirng name){} name是一个变量,变量值可以是张三,也可以是李四 ArrayList<String>这个你理解吗?就是说这个ArrayList集合里存的元素只能是String T你一开始可以理解为Object ArrayList<T>就是说这个ArrayList里存的元素可以是任何类型,T的值可以是String,也可以是Integer <T> void method(ArrayList<T> a1) 最前面的<T>没有实际意义,是在定义泛型方法时的一个固定格式,固定标记 T不需要提前定义,你在调用这个方法的时候,你规定是什么,就是什么 比如你这个方法static <T> void fill(List<? super T> list,T obj) , 调用时可以这样写:Collections.fill(List<Animal>,Cat cat); T你定义为猫,? super T,那么?可以是猫科动物,动物,生物都行,只要是猫的父类
但是这个解释没办法解释我给的第二个例子,第二个例子里面参数部分没有T本体,只有Collection<? extends T> coll 啊
公子寻欢 2016-07-10
  • 打赏
  • 举报
回复
void show(Stirng name){} name是一个变量,变量值可以是张三,也可以是李四 ArrayList<String>这个你理解吗?就是说这个ArrayList集合里存的元素只能是String T你一开始可以理解为Object ArrayList<T>就是说这个ArrayList里存的元素可以是任何类型,T的值可以是String,也可以是Integer <T> void method(ArrayList<T> a1) 最前面的<T>没有实际意义,是在定义泛型方法时的一个固定格式,固定标记 T不需要提前定义,你在调用这个方法的时候,你规定是什么,就是什么 比如你这个方法static <T> void fill(List<? super T> list,T obj) , 调用时可以这样写:Collections.fill(List<Animal>,Cat cat); T你定义为猫,? super T,那么?可以是猫科动物,动物,生物都行,只要是猫的父类

62,614

社区成员

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

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