java高级--------泛型
泛型只是编译时有效,运行时无效
一.自定义泛型方法
1.语法
public <T> T doxx(T t){}
2.示例
编写一个方法,实现指定数组元素交换
/**
* <T>表示声明一个泛型类型T,具体类型在使用时确定
* 其实可以用字母如F来代替T,但通常要大写
* <T>通常需放在方法返回值之前
* <T>定义好一个泛型类型T,则泛型T作为数据类型使用
*/
public static <T> void changeArray(T[] arr, int start, int end){
T t = arr[start];
arr[start] = arr[end];
arr[end] = t;
}
3.规范
java为了规范,建议如下
T 代表一般任何类
E 代表Element的意思,或者Exception异常的意思
K 代表key的意思
V 代表vlaue的意思,通常与K一起使用
4.注意
只有引用类型才能作为泛型方法的实际参数
泛型中同时有多个类型
eg:
public static <K,V> V getValue(Map map , K key){
return (V) map.get(key);
}
二.自定义泛型类
1.定义
如果一个类多处都要用到同一个泛型,可以把泛型定义在类上
2.示例
public class Test<T> {
public void print(List<T> arrayList){
for (T t : arrayList){
System.out.println(t);
}
}
// 静态方法不能使用类定义的泛型,只能单独定义
public static <T> T getValue(T t){
return t;
}
}
3.总结
静态方法不能使用类定义的泛型,只能单独定义
三.通配符
1.定义
通配符?,?代表占位符,表明将来使用时再指明类型。有三种形式
(1).<?>无限定的通配符,是让泛型能够接受未知类型的数据
(2).<? extends E> 有上限的通配符,能接受指定类及其子类的数据!这里不仅可以表示继承关系,也可表示接口E
(3).<? super E> 有下限的通配符,能接受指定类及其父类的数据
2.示例
(1).<?>无限定的通配符,是让泛型能够接受未知类型的数据
/**
* <?>无限定的通配符,是让泛型能够接受未知类型的数据
* ?只是代表一个占位符,因此不算一个类型,也不需要定义类型
* @param list
*/
public void printList(List<?> list){
for (Object o : list){
System.out.println(o);
}
}
(2).<? extends E> 有上限的通配符,能接受指定类及其子类的数据!这里不仅可以表示继承关系,也可表示接口E
/**
* add:除了null之外,不允许加入任何元素
*/
public static void printAnimal(List<? extends Animal> list){
for (Animal animal : list){
// 除了null之外,不允许加入任何元素
//Animal animal1 = new Animal("dsds", "12");
//list.add(animal1);
list.add(null);
System.out.println(animal);
}
}
(3).<? super E> 有下限的通配符,能接受指定类及其父类的数据
// <? super E> 有下限的通配符,能接受指定类及其父类的数据
public static void print(List<? super Cat> list){
// 允许添加cat和Cat的子类元素,还有null
list.add(new Cat("馒头","5"));
list.add(new WhileCat("小黑","3"));
list.add(null);
// 应为不确定传入类型是Cat或Cat父类,因此只能用Object来接收
Object object = list.get(0);
for (Object o : list){
System.out.println(o);
}
}