Java泛型总结

泛型

概念

泛型,即参数化类型。将类型由运来的具体类型参数化。类似于方法中的变量,定义时为形参,使用或被调用时为实参

分类:泛型类、泛型接口、泛型方法

泛型类

定义

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//实例化泛型类时,须指定T的具体类型
public class MyClass<T>{
    private T key;			//key这个成员变量的类型为T,T的类型由外部指定  
    public MyClass(T key) {  //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }
    public T getKey(){ 		//泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

实例化

//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
//传入的实参类型需与泛型的类型参数类型相同,即为Integer
//泛型不能指定基本数据类型,如需使用,应指定其封装类
MyClass<Integer> myClass = new MyClass<Integer>(123456);
//泛型支持java的继承属性,此处泛型指定为List,传入的参数为ArrayList
MyClass<List> myClass = new MyClass<List>(new ArrayList<>());

泛型接口

定义

public interface MyInterface<T> {
    public T method();
}

实例化

//实例化泛型接口时,未指定泛型(用T代替),需将泛型声明加到类中,不加编译报Unknown class错误
class MyClass<T> implements MyInterface<T>{
    @Override
    public T next() {
        return null;
    }
}
//指定泛型,所有使用泛型的地方均需替换一致
public class MyClass implements MyInterface<String> {
    @Override
    public String next() {
       return null;
    }
}

泛型方法

定义

//public与T之间的可理解为声明此方法为泛型方法,泛型类中使用了泛型的成员方法不是泛型方法
public <T> void method(Class<T> tClass){}

使用

method(tClass);

可变参数

public <T> void printMsg( T... args){}

通配符

由于参数类型的不确定,同种泛型可对应多个版本;不同版本的泛型是不兼容的。

为了使不同版本的泛型实例进行兼容,需要传入其所有版本实例的父类引用类型

//方法中指定需要传入的参数,其类型为Object的子类。
public void method(MyClass<? extends Object> myClass){}

MyClass<Integer> myClass1 = new MyClass<>(new Integer(11));
MyClass<String> myClass2 = new MyClass<>("111");
//由于方法中指定的泛型为Object的子类,所以以上两种泛型实例均可传入method()中
method(myClass1);
method(myClass2);

无限定通配符

public void method(Collection collection){}

静态方法与泛型

public class MyClass<T> {
    //静态方法使用泛型必须添加额外的泛型声明,此方法也会变成泛型方法
    public static <T> void show(T t){}
}

泛型上下边界

上边界

//传入的类型实参必须是指定类型的子类型
public class MyClass<T extends List>{
    private T key;
    public Generic(T key) {
        this.key = key;
    }
    public T getKey(){
        return key;
    }
}
public void method(MyClass<? extends Number> obj){}
public <T extends Number> T showName(Generic<T> container){
	...
}

下边界

public void method(MyClass<? super ArrayList> myClass){}

泛型数组

//数组的类型不可以是类型变量,除非是采用通配符的方式
List<String>[] lsa = new List<String>[10];	//错误
List<?>[] lsa = new List<?>[10];		   //正确

泛型擦除

泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉

泛型擦除时,泛型类中的类型参数被替换成类型上限。如未指定上限,则被替换成Object。

List<String> list1 = new ArrayList<String>();
List<Integer> list2 = new ArrayList<Integer>();
System.out.println(list1.getClass() == list2.getClass());	//true,在jvm中的Class都是List.class

类型擦除带来的局限性

类型擦除会抹掉很多继承相关特性

List<Integer> list = new ArrayList<>();
list.add(123);		//正确
list.add("abc");	//错误

绕过类型擦除带来的局限性

List<Integer> ls = new ArrayList<>();
ls.add(23);
try {
	Method method = ls.getClass().getDeclaredMethod("add",Object.class);
	method.invoke(ls,"test");
	method.invoke(ls,42.9f);
} catch (NoSuchMethodException e) {
	e.printStackTrace();
} 

你可能感兴趣的:(Java,Java)