Java中的泛型是什么?

泛型就是在定义类、接口、方法的时候指定某一种特定类型,让类、接口、方法的使用者来决定具体用哪一种类型的参数。

泛型是在1.5引入的,只在编译期做泛型检查,运行期泛型就会消失,称为 泛型擦除,最终类型都会变成Object

泛型的本质是参数化类型,而类型擦除使得类型参数只存在于编译期,在运行时,JVM是并不知道泛型的存在的。

泛型好处

在编译的时候能够检查类型安全,并且所有的强制转换都是自动和隐式的。

类型擦除

1
2
3
4
5
public static void main(String[] args) {
List<String> list1=new ArrayList<String>();
List<Integer> list2=new ArrayList<Integer>();
System.out.println(list1.getClass()==list2.getClass());
}

ArrayList<String>ArrayList<Integer>在编译时是不同的类型,但是在编译完成后都被编译器简化成了ArrayList

为什么要进行泛型的类型擦除?

主要目的是避免过多的创建类而造成的运行时的过度消耗。

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GenericClass<T>{
//成员变量
private T t;

public void function(T t){

}

public T functionTwo(T t){
//注意,这个不是泛型方法!!!
return t;
}
}

泛型接口

1
2
3
4
5
6
7
8
9
10
11
12
public interface GenericInterface<T> {

public T get();

public void set(T t);

public T delete(T t);

default T defaultFunction(T t){
return t;
}
}

泛型函数

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GenericFunction {

public <T> void function(T t) {
}

public <T> T functionTwo(T t) {
return t;
}

public <T> String functionThree(T t) {
return "";
}
}

通配符

通配符是为了让Java泛型支持范围限定。

<?>:无界通配符,即类型不确定,任意类型。

<? extends T>:上边界通配符,即?是继承自T的任意子类型,遵守只读不写。

<? super T>:下边界通配符,即?T的任意父类型,遵守只写不读。

<? extends T>上边界通配符:

  • 不作为函数入参,只作为函数返回类型,比如List<? extends T>的使用add函数会编译不通过,get函数则没问题。

<? super T>下边界通配符:

  • 不作为函数返回类型,只作为函数入参,比如List<? super T>add函数正常调用,get函数也没问题,但只会返回Object,所以意义不大。