泛型的运用理解
参考博客:https://blog.csdn.net/s10461/article/details/53941091
阅后笔记:
一. 概念特性
1.1 泛型,参数化类型,参数包括实参<?><Integer>、形参<T><E>,参数化类型通俗点举例就是:<String> <Integer>
1.2 泛型使用时注意:存入的是自定义类或者包装类如Integer、Character等等,不能使用简单类型的int char 。
1.3 特性:只在编译时生效,编译检测正确的泛型时会被擦除。
二。 具体使用
包含泛型类、泛型接口、泛型方法
2.1 泛型类
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 //在实例化泛型类时,必须指定T的具体类型 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; } }
//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型 //传入的实参类型需与泛型的类型参数类型相同,即为Integer. Generic<Integer> genericInteger = new Generic<Integer>(123456); //传入的实参类型需与泛型的类型参数类型相同,即为String. Generic<String> genericString = new Generic<String>("key_vlaue"); Log.d("泛型测试","key is " + genericInteger.getKey()); Log.d("泛型测试","key is " + genericString.getKey());
泛型类也可以不指定实参
Generic generic = new Generic("111111"); Generic generic1 = new Generic(4444); Generic generic2 = new Generic(55.55); Generic generic3 = new Generic(false);
这样也是可行的。
注意:不能对确切的泛型类型使用instanceof操作。
2.2泛型接口
和泛型类基本类似
/** * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中 * 即:class FruitGenerator<T> implements Generator<T>{ * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class" */ class FruitGenerator<T> implements Generator<T>{ @Override public T next() { return null; } }
2.3泛型通配符
Generic<Ingeter>与Generic<Number>实际上是相同的一种基本类型。
同一种泛型可以对应多个版本,但是这些版本实例化后就不兼容了
例如
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(gNumber); // showKeyValue这个方法编译器会为我们报错:Generic<java.lang.Integer> // cannot be applied to Generic<java.lang.Number> // showKeyValue(gInteger);
解决方案是:
public void showKeyValue1(Generic<?> obj)
值得注意的是,<?>是实参不是形参。可以想象成Object,<?>是所有类型的父类。
2.4泛型方法
public <T,K> K showKeyName(Generic<T> container){ ... }
注意格式,出现多种泛型要在方法名中加入!
方法名前不加<xx>而参数中有形参泛型的属于普通方法。
如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。
注意下列用例
class GenerateTest<T>{ public void show_1(T t){ System.out.println(t.toString()); } //在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型。可以类型与T相同,也可以不同。 //由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,编译器也能够正确识别泛型方法中识别的泛型。 public <E> void show_3(E t){ System.out.println(t.toString()); } //在泛型类中声明了一个泛型方法,使用泛型T,注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。 public <T> void show_2(T t){ System.out.println(t.toString()); } } public static void main(String[] args) { Apple apple = new Apple(); Person person = new Person(); GenerateTest<Fruit> generateTest = new GenerateTest<Fruit>(); //apple是Fruit的子类,所以这里可以 generateTest.show_1(apple); //编译器会报错,因为泛型类型实参指定的是Fruit,而传入的实参类是Person //generateTest.show_1(person); //使用这两个方法都可以成功 generateTest.show_2(apple); generateTest.show_2(person); //使用这两个方法也都可以成功 generateTest.show_3(apple); generateTest.show_3(person); } }

浙公网安备 33010602011771号