一、泛型
1、泛型可以使我们在编译时,而不是运行时检测出错误;
2、之前我们使用过的ArrayList类就是一个泛型类,此外还有泛型接口Comparable;
3、泛型可以将类型参数化,这个能力使我们可以定义带泛型类型的类或方法;
4、泛型类型必须是引用类型,例如:
//此处的泛型可以指定为Integer,但不能指定为int
List list = new ArrayList<>();
5、可以为类或者接口定义泛型,当使用类来创建对象,或者使用类或接口来声明引用变量时,必须指定具体的实例;
6、可以定义一个类或接口作为泛型类或者泛型接口的子类型;
public class String implements Comparable{}
7、定义泛型类(泛型必须放在类名后)
//定义泛型类
public class Demo{}
8、定义泛型方法(泛型必须放在返回值前)
//无参泛型方法
public void print(){}
//有参泛型方法
public void print(E[] list){}
//返回值为泛型的方法
public E print(E[] list){}
//无参静态泛型方法
public static void print(){}
//有参静态泛型方法
public static void print(E[] list){}
9、受限泛型类型(表明泛型必须继承自某类或实现某个接口)
public static> void print(E[] list){}
10、没有指定具体类型的泛型类型称为原始类型,用于和早期的java版本向后兼容,例如:
ArrayList list = new ArrayList();
//这种没有指定具体类型的泛型类型称为原始类型,大体等同于
ArrayList
11、通配泛型类型
(1)、非受限通配
public class Demo {
/**
* 此处并没有限制集合中存储的数据类型,用通配符 '?' 表示
* 这就是 非受限通配
*/
public static double max(ArrayList> list) {
int index = 0;
int maxNum=(Integer) list.get(0);
for(int i=0;imaxNum) {
maxNum=((Integer) list.get(i+1)).intValue();
index=i+1;
}
}
return ((Integer) list.get(index)).doubleValue();
}
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(5);
list.add(0);
list.add(3);
System.out.println(max(list));
}
}
(2)、受限通配
public class Demo {
/**
* 此处表明了'?'必须是 Number的子类,
* 这就是 受限通配
*/
public static double max(ArrayList extends Number> list) {
int index = 0;
int maxNum=(int) list.get(0);
for(int i=0;imaxNum) {
maxNum= list.get(i+1).intValue();
index=i+1;
}
}
return list.get(index).doubleValue();
}
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(5);
list.add(0);
list.add(3);
System.out.println(max(list));
}
}
(3)、下限通配
public class Demo {
/**
* test方法中要求传入的集合中存储的数据必须是String的父类
* Object类型当然是String的父类
* 此处可以传入的参数是T或T的父类
* 这就是 下限通配
*/
public static void test(ArrayList list1,ArrayList super T> list2) {
for (T t : list1) {
System.out.print(t);
}
System.out.println();
for (Object object : list2) {
System.out.println(object);
}
}
public static void main(String[] args) {
ArrayList list1 = new ArrayList<>();
ArrayList
12、消除泛型
泛型存在与编译时,一旦编译器确认了泛型类型是安全使用的,就会将它转换为原始类型,这称为类型消除;
1、比如:集合中用到的泛型,一旦编译器确认了泛型类型是正确且安全使用的,就会将代码转换为需要强制类型转换的原始类型;
2、当编译泛型类、接口、方法时,编译器用Object类型代替泛型类型;
3、如果一个泛型是受限的,那么编译器会用该受限类型来替换泛型;
ArrayList list1 = new ArrayList<>();
ArrayList list2 = new ArrayList<>();
//list1和list2在编译时是单独的两个类型,但当确认泛型的安全性,进入运行之后,代码被转换为原始状态,泛型被消除
list1 instanceof ArrayList;
list1 instanceof ArrayList;
//以上结果均为 true
list1 instanceof ArrayList;
//以上结果为false,因为ArrayList并没有在JVM中单独存储为一个类,泛型在运行时被消除
13、对泛型的限制
1、不能使用泛型类型创建实例;
2、不能使用泛型类型创建数组,但可以创建一个Object类型的数组,将它强制转换为泛型来规避这个限制,但有可能出现类型转换错误异常:
3、在静态上下文中不允许类的参数是泛型;
4、异常类不能是泛型;