泛型
- 类型化参数
- 泛型的好处
- 可以节约代码
- 可以让代码的可读性更强
- 相关的名字:不同字母代表为了见名知意,都是代表类型未知
- T:Type 类型
- E:Element 元素
- K:key
- V:value
- ?:代表任意类型
GenericArrayType:泛化的数组类型,即T[]
ParameterizedType:参数化类型,例如: Comparator< T>,Comparator< String>
TypeVariable:类型变量,例如: Comparator< T>中的T,Map<K, V>中的K, V
WildcardType:通配符类型,例如: Comparator<?>等
- 泛型可以写在哪里?
- 类上:泛型类。例:public class ArrayList< E>
- 接口上:泛型接口。例:public interface List< E>
- 方法上:泛型方法。当方法真正执行的时候,才确定是什么类型。
例:public static < T> boolean addAll(Collection<? super T> c, T… elements) {}
注意:泛型方法的泛型声明放到了返回值的前面
泛型类的使用
public class GenericsTest {
public static void main(String[] args) {
Student<String> s1 = new Student<>("张三","棒");
System.out.println(s1);//Student{name='张三', score=棒}
Student<Integer> s2 = new Student<>("李四", 100);
System.out.println(s2);//Student{name='李四', score=100}
Student<Character> s3 = new Student<>("王五", 'A');
System.out.println(s3);//Student{name='王五', score=A}
}
}
class Student<T>{//类型化参数
String name;
T score;
public Student() {
}
public Student(String name, T score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
}
泛型的上限
import java.math.BigDecimal;
/*
求俩数的和:
*/
public class GenericsTest1 {
public static void main(String[] args) {
SumTools<Integer> s1 = new SumTools<>(10, 20);
System.out.println(s1.getSum());
SumTools<BigDecimal> s2 = new SumTools<>(new BigDecimal("3.14"),new BigDecimal("2.56"));
System.out.println(s2.getSum());
}
}
/**
* T extends Number & Comparable<T>
* T:即使Number的子类也是Comparable的子类
* 指定了当前T的上限:类型范围不能超过父类
*
* @param <T>
*/
class SumTools<T extends Number & Comparable<T>> {
private T t1;
private T t2;
public SumTools() {
}
public SumTools(T t1, T t2) {
this.t1 = t1;
this.t2 = t2;
}
public T getSum() {
if (t1 instanceof Integer) {
Integer value = Integer.valueOf((Integer) t1 + (Integer) t2);
return (T) value;
}else if (t1 instanceof BigDecimal){
BigDecimal b1 = (BigDecimal) t1;
BigDecimal b2 = (BigDecimal) t2;
BigDecimal decimal = b1.add(b2);
return (T) decimal;
}
throw new UnsupportedOperationException("您传入的数据不能进行加法操作");
}
}
泛型擦除
- 当使用参数化类型的类或接口时,如果没有指定泛型,会发生泛型擦除,自动按照最左边的第一个上限处理,如果没有指定上限,上限即为Object。
- 局部变量的泛型在编译后会消失
方法形参、成员变量泛型不会消除
泛型方法
public static <T extends Comparable> void sort(T[] arr){
for (int i = 0; i < arr.length-1 ; i++) {
for (int j = 0; j < arr.length-1-i ; j++) {
if (arr[j].compareTo(arr[j+1])>0){
T temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
类型通配符
E、T、K、V
?:代表任意类型
位置要求:需要传入具体类型的位置,不能单独使用?(声明泛型类、泛型接口、泛型方法时不能单独使用)
?extends T:传入的类型,可以是当前类型,以及当前类型的子类
?super T:传入的类型,可以是当前类型,也可是当前类型的父类
泛型的注意
泛型的限制:当使用?作为泛型的时候,只能传入null值
import java.math.BigDecimal;
import java.util.Date;
public class Test {
public static void main(String[] args) {
MyClass<?> myClass = new MyClass<>();
/*myClass.setFiled(10);
myClass.setFiled(new Date());*/
//泛型的限制:当时用?作为泛型的时候,只能传入null值
myClass.setFiled(null);
//无法确定子类是哪一个,只有null是确定的
//都是Number的子类 以及Number
MyClass<? extends Number> myClass1 = new MyClass<>();
/*myClass1.setFiled(20);
myClass1.setFiled(new Integer(90));
myClass1.setFiled(new BigDecimal(20));
*/
myClass1.setFiled(null);
//都是Number的父类 以及Number
//泛型的下限
MyClass<? super Number> myClass2 = new MyClass<>();
myClass2.setFiled(10);
myClass2.setFiled(new BigDecimal(20));
}
}
class MyClass<T>{
private String name;
private T filed;
public void setFiled(T filed) {
this.filed = filed;
}
}
import java.math.BigDecimal;
import java.util.Date;
public class GenericsEnd {
public static void main(String[] args) {
MyList<String> myList = new MyList<>();
myList.add("你好");
myList.add("世界");
MyList<Number> m1 = new MyList<>();
m1.add(10);
m1.add(new BigDecimal(20));
MyList<Object> m2 = new MyList<>();
m2.add(10);
m2.add(new Date());
copy(m1,m2);
}
/**
*
* @param src ?可能是T,也可能是T的子类 MyList<? extends T> 上限
* @param dest ?可以是T,也可以是T的父类 MyList<? super T> 下限
* @param <T>
*/
public static <T>void copy(MyList<? extends T> src,MyList<? super T> dest){
}
}
class MyList<T>{
public void add(T t){
}
}