java 泛型方法类型推导
2012-08-25 11:36
447 查看
/article/9917954.html
编译器判断泛型方法的实际类型参数的过程叫做类型推断,类型推断的实现方法是一种非常复杂的过程.
根据调用泛型方法时实际传递的参数类型或返回值类型来推断,具体规则如下:
如果某类型变量只在方法参数列表或返回值的一处被调用了,那根据调用该方法时该处的实际类型来确定,即直接根据调用方法时传递的实际类型或方法返回值的类型来确定泛型方法的参数类型.例如: swap(new String[3],3,4) --->static <E> void swap(E[] a,int i,int t)
当某个类型变量在方法的参数列表和返回值中被多次利用了,而且在调用方法时这多处的实际类型又是一样的,那么这也可以很明显的知道此泛型方法的参数类型.例如: add(3,5) --> static <T> T add(T a,T b)
当某个类型变量在方法的参数列表和返回值中被多次利用了,而且在调用方法时这多处的实际类型又对应不同的类型,且返回值是void,那么这时取多处实际变量类型的最大交集.例如: fill(new Integer[3],3.5f) --> static <T> void fill(T[] a,T i) ,此时T为Number,编译不会报错,但运行有问题.
当某个类型变量在方法的参数列表和返回值中被多次利用了,且返回值不为空,在调用方法时这多处的实际类型又对应不同的类型,那么优先考虑返回值的类型.int x = add(3,3.5f) --> static <T> T add(T a,T b)
参数类型的类型推断具有传递性,
copy(new Integer[5],new String[5]) --> static <T> void copy(T[] a, T[] b) T为Object类型,没有问题
copy(new Vector<String>(),new Integer[5]) --> static <T> void copy(Collection<T> a, T[] b) 在new Vector<String>()时决定了T为String类型,而new Integer[5]不是String类型,这样会报错
参考:http://lsq6063.iteye.com/blog/693751
http://www.ibm.com/developerworks/cn/java/j-jtp04298.html
package all;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 对于泛弄的一个总结
* @author root
*
*/
public class Summary {
/*
* 1.为什么 List<? extends T> 可以返回 T 类型的的值,而不能向其中插入 值
* List<? enxtends T> 其中<>中的类型为List存在元素的类型,当然也
* 包括它的子类,如我们定义 List<? extends Number> list,
* 这个list可能为List<Integer>,List<Long>,List<Float>
* 而我们向里面添加的值则可能会是 Integer,Long,Float,Double
* 而假如我们list为 List<Long>而我们向里面添加了 Double,则会
* 出现错误,就是因为我们不知道list中的类型参数是什么类型,因此不
* 能调用List中参数与 E(类型参数)有关的方法,如:list.set(),list.put()等
* 2.为什么List<? extends T>可以返回 T类型的值,无论此时list是List<Integer>
* List<Long>,List<Float>,它们中的已经插入的元素一定都是 Number的子类,因此
* 它们都可以返回Number 类型的元素
*/
public static<T> void get(List<? extends T> list) {
List<Integer> intlist = new ArrayList<Integer>();
}
/**
* 为什么 List<? super T> 可以向list中的插入T类型的值,而get 出来的值只是Object
* List<? super T> 比如:List<? super Integer>,它所传的参数可以为
* List<Number>,List<Comparable>,List<Object>,而向这些集全中添加数据,因为它们
* 都是 Integer的父类,所以,无论它们是前面中的哪一个,都可以向list 中插入Integer数据,
* 而取出数据也是一样,对于 list中插入的数据,我们不知道它是哪一种,我们只是知道它们都是
* Integer的父类,最高为Object,因此,它取出的数据类型就为Object
*
*/
public static<T> void set(List<? super T> list) {
}
/**
* 此方法返回值为任意类型,而其参数一定要实现Comparable接口
* @param <T>
* @param list
* @return
*/
public static<T> T binarySearch(List<? extends Comparable<? super T>> list){
// list.get(0).compareTo(T o) //此list 返回类型为 Comparable<T>
return null;
}
public static<T extends Comparable<? super T>> T max(List<? extends T>list) {
// list.get(0).compareTo(T o)
return null;
}
// 怎么实现向 list<?> 中插入元素,两中方法
public static void addAllType(List<?> list,Object e) {
final List thatlist = list;
thatlist.add(e);
}
public static void main(String args[]) {
List<Integer> intList = new ArrayList<Integer>();
Collections.addAll(intList,1,2,3,4);
List<? extends Number> numList = intList;
Object resulst = numList.get(0);
}
public static void setTest() {
List<Number> numlist = new ArrayList<Number>();
List<Comparable<Integer>> comList = new ArrayList<Comparable<Integer>>();
set(comList);
}
public static void testAllType() {
List<Integer> list = new ArrayList<Integer>();
List<?> lists = list;
}
}
编译器判断泛型方法的实际类型参数的过程叫做类型推断,类型推断的实现方法是一种非常复杂的过程.
根据调用泛型方法时实际传递的参数类型或返回值类型来推断,具体规则如下:
如果某类型变量只在方法参数列表或返回值的一处被调用了,那根据调用该方法时该处的实际类型来确定,即直接根据调用方法时传递的实际类型或方法返回值的类型来确定泛型方法的参数类型.例如: swap(new String[3],3,4) --->static <E> void swap(E[] a,int i,int t)
当某个类型变量在方法的参数列表和返回值中被多次利用了,而且在调用方法时这多处的实际类型又是一样的,那么这也可以很明显的知道此泛型方法的参数类型.例如: add(3,5) --> static <T> T add(T a,T b)
当某个类型变量在方法的参数列表和返回值中被多次利用了,而且在调用方法时这多处的实际类型又对应不同的类型,且返回值是void,那么这时取多处实际变量类型的最大交集.例如: fill(new Integer[3],3.5f) --> static <T> void fill(T[] a,T i) ,此时T为Number,编译不会报错,但运行有问题.
当某个类型变量在方法的参数列表和返回值中被多次利用了,且返回值不为空,在调用方法时这多处的实际类型又对应不同的类型,那么优先考虑返回值的类型.int x = add(3,3.5f) --> static <T> T add(T a,T b)
参数类型的类型推断具有传递性,
copy(new Integer[5],new String[5]) --> static <T> void copy(T[] a, T[] b) T为Object类型,没有问题
copy(new Vector<String>(),new Integer[5]) --> static <T> void copy(Collection<T> a, T[] b) 在new Vector<String>()时决定了T为String类型,而new Integer[5]不是String类型,这样会报错
package all; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * java 泛型方法的类型推断 * @author root * */ public class TypeInfer { /** * 1.类型变量只在方法参数列表或返回值中的一处被调用, * 那么类型推测的结点就是直接传递 的参数类型或返回的值的类型 * @param <T> * @param value */ public static<T> void onlyOneCall(T value){ System.out.println(value); } /** *参数多次调用且传递参数类型相同,那么就会传入参数的实际类型 * @param <T> * @param a * @param b * @return */ public static<T> T sameParam(T a,T b){ return a; } /** * 有多个参数,且传入实参的类型都不一样,推断的出的类型则是它们的交集,运行时可能会错误 * 如: noSamePram(new Integer[2],new Float(2.0))//此时推断出来的类型为 Number,但会运行错误 * @param <T> * @param array * @param b */ public static<T> void noSameParam(T[]array,T b){ int len = array.length; for(int i=0;i<len;i++) array[i] = b; } /** * 有多个参数,传入值类型不同,而且有返回值,那么会优先考虑返回 值 * @param <T> * @param a * @param b * @return */ public static<T> T noSameParamWithReturn(T a,T b){ return b; } /** * 类型推断具有传递性,如果参数中有需要推断的类型,如果list<T>此的T就是传递进来的参数的值的类型,如 * copy(new List<String> list,new Integer(1)),T就为 string,而此时array为integer,两者不现,不会再取 * 交集,会编译错误,因此,在参数中的泛型的泛型方法中,传递的参数一定保持一致 * 如: copy(Collection<T> col,T[]array),copy(new List<String>,new Integer[]) 首先推断出 T 类型为 string,而后面的是 Integer,所以错误 * @param <T> * @param col * @param array */ public static<T> void copy(Collection<T>col,T[]array){ } public static<T> T copycopy(T[]array,Collection<T>col){ return array[0]; } public static<T> T copy(T a,T b){ return a; } public static void main(String args[]){ Integer a = new Integer(1); Long b = new Long(2); //noSameParam(new Integer[3],new Float(1)); List<String> list = new ArrayList<String>(); Integer [] array = new Integer[]{1,2,3}; copy(list,array); copy(array,list); copy(new String(),new Integer(2)); } }
参考:http://lsq6063.iteye.com/blog/693751
http://www.ibm.com/developerworks/cn/java/j-jtp04298.html
package all;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 对于泛弄的一个总结
* @author root
*
*/
public class Summary {
/*
* 1.为什么 List<? extends T> 可以返回 T 类型的的值,而不能向其中插入 值
* List<? enxtends T> 其中<>中的类型为List存在元素的类型,当然也
* 包括它的子类,如我们定义 List<? extends Number> list,
* 这个list可能为List<Integer>,List<Long>,List<Float>
* 而我们向里面添加的值则可能会是 Integer,Long,Float,Double
* 而假如我们list为 List<Long>而我们向里面添加了 Double,则会
* 出现错误,就是因为我们不知道list中的类型参数是什么类型,因此不
* 能调用List中参数与 E(类型参数)有关的方法,如:list.set(),list.put()等
* 2.为什么List<? extends T>可以返回 T类型的值,无论此时list是List<Integer>
* List<Long>,List<Float>,它们中的已经插入的元素一定都是 Number的子类,因此
* 它们都可以返回Number 类型的元素
*/
public static<T> void get(List<? extends T> list) {
List<Integer> intlist = new ArrayList<Integer>();
}
/**
* 为什么 List<? super T> 可以向list中的插入T类型的值,而get 出来的值只是Object
* List<? super T> 比如:List<? super Integer>,它所传的参数可以为
* List<Number>,List<Comparable>,List<Object>,而向这些集全中添加数据,因为它们
* 都是 Integer的父类,所以,无论它们是前面中的哪一个,都可以向list 中插入Integer数据,
* 而取出数据也是一样,对于 list中插入的数据,我们不知道它是哪一种,我们只是知道它们都是
* Integer的父类,最高为Object,因此,它取出的数据类型就为Object
*
*/
public static<T> void set(List<? super T> list) {
}
/**
* 此方法返回值为任意类型,而其参数一定要实现Comparable接口
* @param <T>
* @param list
* @return
*/
public static<T> T binarySearch(List<? extends Comparable<? super T>> list){
// list.get(0).compareTo(T o) //此list 返回类型为 Comparable<T>
return null;
}
public static<T extends Comparable<? super T>> T max(List<? extends T>list) {
// list.get(0).compareTo(T o)
return null;
}
// 怎么实现向 list<?> 中插入元素,两中方法
public static void addAllType(List<?> list,Object e) {
final List thatlist = list;
thatlist.add(e);
}
public static void main(String args[]) {
List<Integer> intList = new ArrayList<Integer>();
Collections.addAll(intList,1,2,3,4);
List<? extends Number> numList = intList;
Object resulst = numList.get(0);
}
public static void setTest() {
List<Number> numlist = new ArrayList<Number>();
List<Comparable<Integer>> comList = new ArrayList<Comparable<Integer>>();
set(comList);
}
public static void testAllType() {
List<Integer> list = new ArrayList<Integer>();
List<?> lists = list;
}
}
相关文章推荐
- java 泛型方法类型推导
- java 泛型方法类型推导
- 详谈Java8新特性泛型的类型推导
- Java 泛型的类型擦除和桥方法
- java 如何理解泛型类(类型擦除、翻译泛型表达式,翻译泛型方法)
- java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束
- [bxd学习java基本点]13泛型类,泛型方法,当定义二种类型的泛型方法时,用迭代器的方法
- Java获取泛型参数的类型的方法 - 实例讲解
- 泛型方法-类型推导
- java-泛型返回值的方法类型
- 黑马程序员--Java基础加强--15.利用反射操作泛型IV【通过反射Method解析泛型方法思路】【通过Method对四种Type子接口类型进行解剖】【使用递归对任意复合泛型类型进行彻底解剖】【个人
- JAVA中取得泛型类型方法
- [bxd学习java基本点]13泛型类,泛型方法,当定义二种类型的泛型方法时,用迭代器的方法
- [疯狂Java]泛型:泛型方法、泛型方法VS类型通配符(?)
- java中的方法返回值使用泛型,实现灵活的返回值类型
- Java 5.0 泛型之 通过泛型方法返回泛型类型
- java 泛型的类型擦除与桥方法
- Java 8 新特性之泛型的类型推导
- Java 中取得泛型类型的方法
- java 反射机制(通过getGenericSuperclass()方法获取到父类泛型的类型)