综述
泛型,也即参数化类型,所谓的参数化类型,也就是将原来的具体的类型参数化,类似于方法中的类型参数,此时参数的类型也定义成了参数形式,然后在调用时传入具体的类型。
泛型的本质就是参数化类型,也就是在泛型使用的过程中操作的数据类型被指定为一个参数,这种类型可以用在类、接口和方法中,分别构成泛型类、泛型接口和泛型方法。
1、泛型的特性
泛型只在编译阶段有效,在编译之后程序会采用去泛型化的操作,下面的例子就可以证明:
List<String> stringList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();
if (stringList.getClass().equals(integerList.getClass())){
System.out.println("类型相同");
}
结果会打印类型相同
2、泛型的使用
一些常用的泛型类型变量:
E:元素(Element),多用于java集合框架
K:关键字(Key)
N:数字(Number)
T:类型(Type)
V:值(Value)
- ①、泛型类
可以对泛型类这样设计,如下:
public class Generic<T,E>{
private T name;
private E password;
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
public E getPassword() {
return password;
}
public void setPassword(E password) {
this.password = password;
}
}
使用的时候和集合使用基本一致:
Generic<String,String> generic1 = new Generic<>();
Generic<String,Integer> generic2 = new Generic<>();
…… ……
- ②、泛型接口
泛型接口定义如下形式:
public interface GenericInterface<T,E> {
T get();
Object get(E e);
Object get(T t,E e);
}
实现类方式如下:
public class Generic implements GenericInterface<String, Integer>{
@Override
public String get() {
return null;
}
@Override
public Object get(Integer integer) {
return null;
}
@Override
public Object get(String s, Integer integer) {
return null;
}
}
当然也可以这样实现:
public class Generic<T,E> implements GenericInterface<T, E>{
@Override
public T get() {
return null;
}
@Override
public Object get(E e) {
return null;
}
@Override
public Object get(T t, E e) {
return null;
}
}
实现泛型接口时,未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中;
- ③、泛型方法
泛型方法定义形式可如下所示:
public static <T> T get(T t){
System.out.println(t.getClass().getName() + " " + t);
return t;
}
3、泛型的上下边界
在使用泛型的时候还可以为传入的泛型类型实参进行上下边界的限制,如只准传入某种类型的父类或者子类。
extends 表示只准传入子类型,super表示只准传入父类型,使用问号( ? )做通配符。
public static <T> void sort(T[] a, Comparator<? super T> c)
4、类型擦除
类型擦除在编译期发生,如果类型参数没有任何限制时,会类型擦除时被直接替换为Object,当有上下界时会被替换为上下界。