泛型可以让编译器帮助我们在编译阶段识别出类型和给出的类型符不符合。
泛型只在编译阶段有效,在运行时泛型信息会被擦除,也就是说泛型在逻辑上是不同的类型,但是实际上都是相同的基本类型。
反型的使用
泛型类
方法签名类似:public class Generic
在类签名声明了泛型
例如:
private T key;
public Generic(T key)
public T getKey();
使用:
Generic<Integer> genericInteger = new Generic<Integer>(123456);
Generic<String> genericString = new Generic<String>("key_vlaue");
Log.d("泛型测试","key is " + genericInteger.getKey());
Log.d("泛型测试","key is " + genericString.getKey());
泛型接口
使用:public interface Generator
当实现这个接口时,如果没有为泛型指定类型。则需要在类签名中也声明泛型;
例如:class FruitGenerator implements Generator{}
当为这个泛型指定了类型,则在这个接口中使用了这个泛型的方法在实现接口的类方法中也需要使用这个类型。
例如(嫁入这个接口的next()方法使用了这个泛型参数):
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)];
}
}
泛型通配符
当具体类型不确定时,可以使用泛型通配符’?’。
此处的?和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。是一种真实的类型。
泛型方法
基本使用:
/*
* 这才是一个真正的泛型方法。
* 首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
* 这个T可以出现在这个泛型方法的任意位置.
* 泛型的数量也可以为任意多个
* 如:public <T,K> K showKeyName(Generic<T> container){
* ...
* }
*/
泛型方法,泛型在方法签名里声明,然后在方法返回值,方法参数表,方法体中使用。
类中的泛型方法:
如果类是泛型类,方法也是泛型方法,假如类声明的泛型是
泛型方法与可变参数
使用:
public <T> void printMsg( T... args){
for(T t : args){
Log.d("泛型测试","t is " + t);
}
}
printMsg("111",222,"aaaa","2323.4",55.55);
静态方法与泛型
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 void showKeyValue1(Generic<? extends Number> obj){
Log.d("泛型测试","key value is " + obj.getKey());
}
Generic<String> generic1 = new Generic<String>("11111");
Generic<Integer> generic2 = new Generic<Integer>(2222);
Generic<Float> generic3 = new Generic<Float>(2.4f);
Generic<Double> generic4 = new Generic<Double>(2.56);
//这一行代码编译器会提示错误,因为String类型并不是Number类型的子类
//showKeyValue1(generic1);
showKeyValue1(generic2);
showKeyValue1(generic3);
showKeyValue1(generic4);
如果我们把泛型类的定义也改一下:
public class Generic<T extends Number>{
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey(){
return key;
}
}
-----------------------------------------------
//这一行代码也会报错,因为String不是Number的子类
Generic<String> generic1 = new Generic<String>("11111");