Java-泛型
1.泛型概述
- 泛型本质上是提供类型的“类型参数”,也就是参数化类型。
我们可以为类、接口或方法指定一个类型参数,通过这个参数限制操作的数据类型,从而保证类型转换的绝对安全。
泛型可以在编译时检查类型安全,并且所有强制转换都是自动和隐式的,提高了代码的重用率。
运行期间泛型会“忘记类型”,转为Object
示例:通过反射向Integer的List中添加String类型(编译不会报错)
List<Integer> list = new LinkedList<>();
list.add(11);
Class clazz = list.getClass();
Method method = clazz.getDeclaredMethod("add", Object.class);
method.invoke(list, "Hello");
2. 泛型集合
注:Java 集合有个缺点,就是把一个对象“丢进”集合里之后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了 Object 类型(其运行时类型没变)。
Java1.5提供了泛型,可实现自动隐式类型转换。
eg.
Map<Integer, Book> books = new HashMap<Integer, Book>();
上述代码指明了该 Map 集合中存放的键必须是 Integer 类型、值必须为 Book 类型,否则编译出错。
在获取 Map 集合中的元素时,不需要将books.get(id);获取的值强制转换为 Book 类型,程序会隐式转换。
3 泛型类
使用场景:泛型类一般用于类中的属性类型不确定的情况下.
3.1 泛型类定义与属性声明
泛型类定义语法格式如下:
public class class_name<data_type1,data_type2,…>{}
声明属性如下:
private data_type1 property_name1; private data_type2 property_name2;
3.2 泛型类实例化
eg.
public class Stu <N, A, S>{
private N name;
private A age;
private S sex;
public Stu(N name, A age, S sex){
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return name + " " + age + " " + sex;
}
public static void main(String[] args){
Stu stu = new Stu("Mike", 22, 'M');
System.out.println(stu.sex.getClass());
}
}
在获取学生姓名、年龄和性别时,不需要类型转换,程序隐式地将 Object 类型的数据转换为相应的数据类型。
3 泛型方法
泛型同样可以在类中包含参数化的方法,而方法所在的类可以是泛型类,也可以不是泛型类。也就是说,是否拥有泛型方法,与其所在的类是不是泛型没有关系。
泛型方法使得该方法能够独立于类而产生变化。如果使用泛型方法可以取代类泛型化,那么就应该只使用泛型方法。另外,对一个 static 的方法而言,无法访问泛型类的类型参数。因此,如果 static 方法需要使用泛型能力,就必须使其成为泛型方法。
3.1 泛型方法的定义格式
[访问权限修饰符] [static] [final] <类型参数列表> 返回值类型 方法名([形式参数列表])
实例:
public static <T> List find(Class<T> cs,int userId){}
一般来说编写 Java 泛型方法,其返回值类型至少有一个参数类型应该是泛型,而且类型应该是一致的,如果只有返回值类型或参数类型之一使用了泛型,那么这个泛型方法的使用就被限制了。
3.2 具体实例
基于上述stu类新增show方法显示类信息(不限于Stu类)
public static <T> void show(T stu){
System.out.println(stu);
}
4 类型通配符
4.1 概述
类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类。
实例:
private static void showList(List<\?> list){ //无\
for(int i = 0; i < list.size(); i++){
System.out.println(list.get(i) + " ");
}
}
4.2 类型通配符的父子类型
- <? extends T>表示该通配符所代表的类型是T类型的子类或实现类。表示通配符泛型值接受T及其下层子类类型。
- <? super T>表示该通配符所代表的类型是T类型的父类。表示类型只能接受T及其父类类型.
5 泛型的高级用法
5.1 限制泛型可用类型(对泛型类实例的类型进行限制)
用法示例:
class 类名称<T extends anyClass>
5.2 继承泛型类和实现泛型接口
定义为泛型的类和接口也可被继承和实现。
public class FatherClass<T1>{}
public class SonClass<T1,T2,T3> extents FatherClass<T1>{}
6 泛型注意事项
- 不能使用基本类型作为泛型类型 (类型擦除)
- 泛型类中不能设置静态属性、方法、代码块为泛型: 泛型类型在对象创建时才被确定,而静态属性、方法、代码块在构造函数之前就已经确定,因此对于静态部分引用的泛型虚拟机无法确定具体类型 - 该类还未被初始化。
- 不能构造泛型数组 - Pair<String>[] 可以存储Pair<Integer>
- 可通过
List\<Pair\<String>>来存储泛型数组 - 对于无限制参数类型T... t, 规则有所放松,只会得到警告且可抑制
- 可通过
- 不能实例化类型变量T t = new T(); (类型擦除后得到的是new Object())
- 抛出、捕获泛型类实例需限制Throwable
<T extends Throwable>

浙公网安备 33010602011771号