<类型>这种语法形式就叫泛型。
其中:
什么时候使用泛型类或泛型接口呢?
-
<T>是类型变量(Type Variables),而<T>是代表未知的数据类型,我们可以指定为<String>,<Integer>,<Circle>等,那么<类型>的形式我们成为类型参数;
-
类比方法的参数的概念,我们可以把<T>,称为类型形参,将<Circle>称为类型实参,有助于我们理解泛型;
-
-
Comparator<T>这种就称为参数化类型(Parameterized Types)。
-
GenericArrayType:泛化的数组类型,即T[]
-
ParameterizedType:参数化类型,例如:Comparator<T>,Comparator<String>
-
TypeVariable:类型变量,例如:Comparator<T>中的T,Map<K,V>中的K,V
-
WildcardType:通配符类型,例如:Comparator<?>等
-
在哪里可以声明类型变量<T>
-
声明类或接口时,在类名或接口名后面声明类型变量,我们把这样的类或接口称为泛型类或泛型接口
【修饰符】 class 类名<类型变量列表> 【extends 父类】 【implements 父接口们】{ } 【修饰符】 interface 接口名<类型变量列表> 【implements 父接口们】{ } 例如: public class ArrayList<E> public interface Map<K,V>{ .... }
注意:
-
<类型变量列表>:可以是一个或多个类型变量,一般都是使用单个的大写字母表示。例如:<T>、<K,V>等。
-
<类型变量列表>中的类型变量不能用于静态成员上。
-
当某个类的非静态实例变量的类型不确定,需要在创建对象或子类继承时才能确定
-
当某个(些)类的非静态方法的形参类型不确定,需要在创建对象或子类继承时才能确定、
声明方法时,在【修饰符】与返回值类型之间声明类型变量,我们把声明(是声明不是单纯的使用)了类型变量的方法称为泛型方法
-
【修饰符】 <类型变量列表> 返回值类型 方法名(【形参列表】)【throws 异常列表】{ //... } 例如:java.util.Arrays类中的 public static <T> List<T> asList(T... a){ .... }
1)实际类型参数必须是引用数据类型,不能是基本数据类型(2)在创建类的对象时指定类型变量对应的实际类型参数(3)在继承泛型类或实现泛型接口时,指定类型变量对应的实际类型参数
-
类型变量的上限
当在声明类型变量时,如果不希望这个类型变量代表任意引用数据类型,而是某个系列的引用数据类型,那么可以设定类型变量的上限。
-
语法格式:
-
<类型变量 extends 上限>
-
如果有多个上限
-
<类型变量 extends 上限1 & 上限2>
-
类型通配符
当我们声明一个变量/形参时,这个变量/形参的类型是一个泛型类或泛型接口,例如:Comparator<T>类型,但是我们仍然无法确定这个泛型类或泛型接口的类型变量<T>的具体类型,此时我们考虑使用类型通配符。
-
<? extends 上限>
例如:我们要声明一个学生管理类,这个管理类要包含一个方法,找出学生数组中成绩最高的学生对象。
要求学生的成绩的类型必须可比较大小,实现Comparable接口。
class StudentService { @SuppressWarnings({ "rawtypes", "unchecked" }) public static Student<? extends Comparable> max(Student<? extends Comparable>[] arr){ Student<? extends Comparable> max = arr[0]; for (int i = 0; i < arr.length; i++) { if(arr[i].getScore().compareTo(max.getScore())>0){ max = arr[i]; } } return max; } } public class TestGeneric { @SuppressWarnings({ "rawtypes", "unchecked" }) public static void main(String[] args) { Student<? extends Double>[] arr = new Student[3]; arr[0] = new Student<Double>("张三", 90.5); arr[1] = new Student<Double>("李四", 80.5); arr[2] = new Student<Double>("王五", 94.5); Student<? extends Comparable> max = StudentService.max(arr); System.out.println(max); } }
<? super 下限>
现在要声明一个数组工具类,包含可以给任意对象数组进行从小到大排序,只要你指定定制比较器对象,而且这个定制比较器对象可以是当前数组元素类型自己或其父类的定制比较器对象
数组工具类:
class MyArrays{ public static <T> void sort(T[] arr, Comparator<? super T> c){ for (int i = 1; i < arr.length; i++) { for (int j = 0; j < arr.length-i; j++) { if(c.compare(arr[j], arr[j+1])>0){ T temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } } class Person{ private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "name=" + name + ", age=" + age; } } class Student extends Person{ private int score; public Student(String name, int age, int score) { super(name, age); this.score = score; } public Student() { super(); } public int getScore() { return score; } public void setScore(int score) { this.score = score; } @Override public String toString() { return super.toString() + ",score=" + score; } } public class TestGeneric { public static void main(String[] args) { Student[] all = new Student[3]; all[0] = new Student("张三", 23, 89); all[1] = new Student("李四", 22, 99); all[2] = new Student("王五", 25, 67); MyArrays.sort(all, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } }); System.out.println(Arrays.toString(all)); MyArrays.sort(all, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getScore() - o2.getScore(); } }); System.out.println(Arrays.toString(all)); } }