泛型:JDK1.5以后出现,解决安全机制
1.将运行时期出现的问题ClassCastException 转移到了编译时期
方便与程序员解决问题,让运行时期问题减少,安全
2.避免了强制转换的麻烦
使用泛型集合,将元素限定为一个特定的类型,集合中只能存储同一个类型的对象,编译器阻挡非法输入
ArrayList<E> E 类型变量,类型参数
ArrayList<Integer> Integer实际类型参数
< >读音 typeof
在创建数组实例时,数组的元素不能使用参数化的类型
泛型格式
<>来定义要操作的引用数据类型
在使用java提供的对象时,,什么时候使用泛型
通常在集合框架中很常见
其实<> 就是用来接受类型的
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可
? 通配符 也可理解为占位符。
泛型的限定:
? extends E: 可以接受E类型或者E的子类型 上限
? super E: 可以接受E类型或者E的父类型 下限
提示:限定通配符总是包括自己
在泛型中可以同时有多个参数,用逗号分隔
public static <K , V> getValue(K key){
return map.get(key);
}
体现方式:
1.ArrayList collection1 = new ArrayList();
collection1.add(1);
collection1.add(1L);
collection1.add("abc");
int i = (Integer) collection1.get(0);
此方式为之前的定义,需要进行强制转换才能得到相应的数据。
2.ArrayList<String> collection2 = new ArrayList<String>();
//collection2.add(1);
//collection2.add(1L);
collection2.add("abc");
String element = collection2.get(0);
System.out.println(element);
限定String类型,这样就只能存储字符串
3.Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);
String str2 = constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2);
构造方法也可以使用泛型。
两个泛型参数
HashMap<String,Integer> maps = new HashMap<String,Integer>();
maps.put("guiwang", 99);
maps.put("xiaoao", 98);
maps.put("jianghu", 100);
Set<Map.Entry<String,Integer>> entryset = maps.entrySet();
for(Map.Entry<String, Integer> entry:entryset){
System.out.println(entry.getKey() + "::" + entry.getValue());
}
具体应用实例:
private static <T> T add(T x,T y){
return null;
}
add(3,5);
Number x =add(3.5,3);
add("abc",3);
private static<T> void swap(T[]a,int i,int j){
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
swap(new String[] {"abc","xyz"},0,1);
//只有引用类型才能作为泛型方法的实际参数,所以下面是错的。
// swap(new int[]{1,2,3},1,2);
//类型参数的类型推断
GenericDao <ReflectPoint> dao = new GenericDao<ReflectPoint>();
dao.add(new ReflectPoint(3,3));
类型参数的类型推断
编译器判断泛型方法的实际类型参数的过程成为类型推断,类型推断是相对于知觉推断的,其实现方法是一种非常复杂的过程。
根据调用泛型方法时实际传递的参数类型或返回值的类型来推断,具体规则如下:
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,并且使用返回值,这时候优先考虑返回值的类型,例如,下面语句实际对应的类型就是Ingeger了,编译将报告错误,将变量x的类型改为float,对比eclipse报告的错误提示,接着再将变量x类型改为Number,则没有了错误
Int x = (3,3,5f)à static <T> T add(T a, T b)
参数类型的类型推断具有传递性,下面第一种情况推断实际参数类型为Object,编译没有问题,而,第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题:
Copy(new Integer[5], new String [ 5]) -à static <T> void copy (T [ ] a, T [ ] b)
当某个类型变量在整个参数列表中的说有参数和返回值的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时读取多个参数中的最大交集类型,例如,下面语句实际对应的类型就是Numberl,编译没有问题,只是运行时出问题
Fill(new Integer[ 3], 3.5f)à static <T> void fill(T[ ] a,T v)
当某个类型变量在整个参数列表中的所有参数和返回值中的多出被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定,这很容易凭着感觉推断出来,例如:
add(3,5)-àstatic<T> T add(T a,T b);
当某个类型变量只在整个参数列表中的所有参数和返回值的一处被应用了,那么根据调用方法时该处的实际应用类型确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值来决定泛型参数的类型
Swap(new String[3],1,2)-àstatic <E> void swap(E[ ] a, int I, int j)