文章来源:https://blog.youkuaiyun.com/s10461/article/details/53941091
(建议去看原文章,非常详细,以下只是我从原文章总结摘录的一部分,为了便于我自己理解)
泛型类:
泛型类,是在实例化类的时候指明泛型的具体类型。
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
public class Generic<T>{
//key这个成员变量的类型为T,T的类型由外部指定
private T key;
public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
this.key = key;
}
public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
return key;
}
}
- 泛型的类型参数只能是类类型,包括基本类型的封装类和自定义的类,总之不能是int这样的简单类型。
- 泛型类在实例化时必须指定泛型类型。
- 泛型类上声明的泛型,可在类中任意位置使用,如成员变量、方法内部、方法返回值等。
泛型方法:
泛型方法,是在调用方法的时候指明泛型的具体类型。
-
声明泛型方法:通过 在访问修饰符与返回值之间添加(也可以是其他字母),来声明这是一个泛型方法。
-
区分泛型类与泛型方法:泛型类是在类名后紧接一个着加,在类中可以使用此泛型来定义方法,如用该泛型来将方法的返回值由具体的类型变为泛 型,将方法的参数变为泛型。泛型方法是则是指必须在访问修饰符和返回值之间用将方法声明为泛型方法。
Class fruit<T>{...} //泛型类 public <T> T query(){...} //泛型方法
-
泛型的数量也可以为任意多个 。泛型方法声明的泛型可以是区别于泛型类中声明过的新泛型,新泛型在泛型方法中的任意位置使用。
public <T,K> K showKeyName(Generic<T> container){...}
-
静态方法如果想使用泛型,不管是用来泛型化返回值还是泛型化形参,或者是其他位置,都必须将该方法声明为静态方法,因为静态方法静态方法无法访问类上定义的泛型,除非借助泛型方法才能使用泛型能力。
public class StaticGenerator<T> { .... .... /** * 如果在类中定义使用泛型的静态方法,需要添加额外的泛型声明(将这个方法定义成泛型方法) * 即使静态方法要使用泛型类中已经声明过的泛型也不可以。 * 如:public static void show(T t){..},此时编译器会提示错误信息: "StaticGenerator cannot be refrenced from static context" */ public static <T> void show(T t){ } }
-
在泛型方法中添加上下边界限制的时候,必须在访问修饰符和返回值之间的上添加上下边界。
//错误写法:public <T> T showKeyName(Generic<T extends Number> container),编译器会报错:"Unexpected bound" //以下为正确写法 public <T extends Number> T showKeyName(Generic<T> container){ System.out.println("container key :" + container.getKey()); T test = container.getKey(); return test; }
泛型接口:
实现泛型接口,有两种使用方法:
-
一是未给泛型接口传入具体类型,在这种情况下,实现类必须将泛型声明一并加入类中。
class FruitGenerator<T> implements Generator<T>{ @Override public T next() { return null; } }
-
二是传入了具体类型,在这种情况下,所有使用泛型的地方都要替换成传入的实参类型。
public class FruitGenerator implements Generator<String> { private String[] fruits = new String[]{"Apple", "Banana", "Pear"}; @Override public String next() { Random rand = new Random(); return fruits[rand.nextInt(3)]; } }
泛型通配符:
泛型的类型参数为子类时,不能作为泛型类型为父类方法的参数,即类型的父子关系不能实现参数类型的兼容。泛型通配符用于解决此种问题,“?”作为一个具体的泛型类型看待,相当于所有类型的父类,是一种真实的类型。用?来表示未知类型。
public void showKeyValue1(Generic<Number> obj){
Log.d("泛型测试","key value is " + obj.getKey());
}
Generic<Integer> gInteger = new Generic<Integer>(123);
Generic<Number> gNumber = new Generic<Number>(456);
showKeyValue(gInteger); //✘
// showKeyValue这个方法编译器会为我们报错:Generic<java.lang.Integer>
// cannot be applied to Generic<java.lang.Number>
泛型数组:
List<String>[] ls = new ArrayList<String>[10]; // ✘
List<?>[] ls = new ArrayList<?>[10]; // ✔
List<String>[] ls = new ArrayList[10]; // ✔