首页 > 代码库 > Java中的泛型
Java中的泛型
1.泛型的概念
Java中我们说的泛型指的泛化的类型,如在定义iterator方法时 <E> 就是指的泛型,在实际声明时可以用特定的引用类型替代<>中的字母,如
ArrayList<String> arrString = new ArrayList<>();
该语句实现了指向String对象的 ArrayList容器的声明。
2.泛型的作用
在使用容器时,为了免于类型转化的麻烦,在定义容器时加上泛型并制定引用类型可以确保类型安全,同时动态绑定时无需做显式类型转换。
3. 泛型的自定义
在自定义泛型时,泛型的<>放在类型后面,括号中可以用单个字母表示(E:element , T:Type , K:key , V:value)
1 public class Student <T>{ 2 private T grade; 3 4 public Student(T grade){ 5 this.grade = grade; 6 } 7 public Student(){ 8 } 9 10 public T getGrade() { 11 return grade; 12 } 13 14 public void setGrade(T grade) { 15 this.grade = grade; 16 } 17 }
在定义和使用泛型时需要注意:① 泛型不能运用在静态属性上 ② 使用泛型时,实现的类型不能是基本类型而必须是引用类型。类似的泛型还可以用来定义接口和方法。
4.泛型的继承
泛型的继承满足: ① 若保留父类泛型 则 子类为泛型子类 ② 若不保留父类泛型 则子类按需要实现即可
1 class Father<T1,T2>{ 2 3 } 4 // 父类泛型全部保留,子类也需要全部保留,子类泛型个数 >= 父类 5 class C1<T1,T2,A,B> extends Father<T1,T2>{ 6 } 7 // 父类泛型部分保留,子类也要保留父类中现有泛型,此外子类可以根据自己的需要增加其他类型 8 class C2<A,T2,B> extends Father<Integer,T2>{ 9 } 10 // 父类泛型为具体类型,子类可以根据自己需要来使用泛型(可以不使用) 11 class C3<A> extends Father<Integer,String>{ 12 } 13 // 父类为非泛型类,子类可以是也可以不是泛型类 14 class C4<A,B>extends Father{ 15 }
5.泛型的擦除
泛型的擦除指的在使用/继承/实现 时没有指定类型,默认泛型的实际类型类似与Object,但不等同与Object 如:
1 ArrayList arrayList = new ArrayList(); //类似于下一行 2 // ArrayList<Object> arrayList = new ArrayList<>();
6.泛型的通配符及上下限
当<T>中可以实现的不止一种类型时,我们可以采用<?>来代表 Object或者Object的所有子类。此外通过采用 extends 和 super两个
关键字,可以将类型指定在某个范围内。如
1 public static void main(String[] args) { 2 3 List<? extends Fruit> list1 = new ArrayList<Apple>(); 4 test(list1); 5 List<? extends Apple> list2 = new ArrayList<Apple>(); 6 test(list2); 7 List<? extends Apple> list3 = new ArrayList<FujiApple>(); 8 test(list3); 9 List<?> list4 = new ArrayList<Apple>(); 10 // test(list4); // List<?> list4 相当于 List<? extends Object> list4 因此 11 // 当List<? extends Fruit> 类型的形参只能接收Fruit类或者它的子类作为参数 12 } 13 14 public static void test(List<? extends Fruit> list){ 15 // list.add(new Apple()); //这里无法添加是因为list有可能是Apple的子类的容器,子类的容器无法保存父类的引用 16 list.add(null); 17 }
上例中满足 Apple,Banana类为Fruit的子类 ,FujiApple为Apple的子类。 当test方法的参数为List<? extends Fruit>类型的容器时,list4无法作为实参传入
因为Object 为Fruit类的父类。
1 public static void main(String[] args) { 2 List<? super Apple> list5 = new ArrayList<Apple>(); 3 test1(list5); 4 List<? super FujiApple> list6 = new ArrayList<Apple>(); 5 // test1(list6); // List<? super FujiApple> 类型的范围超过了List<? super Apple>因此无法调用 6 List<? super Apple> list7 = new ArrayList<Fruit>(); 7 test1(list7); 8 List<? super Apple> list8 = new ArrayList<Object>(); 9 test1(list8); 10 } 11 12 public static void test1(List<? super Apple> list){ 13 list.add(new FujiApple()); 14 list.add(new Apple()); 15 // list.add(new Fruit()); //这里Fruit类型为Apple的父类,容器list在确保安全的情况下最高只能添加Apple类的对象 16 list.add(null); 17 }
类似的 <? super Apple> 类型的容器的对象类型不能超过Apple类型(不能是Apple类型的父类),而作为实参 传入test1的类型的范围不能大于<? super Apple>的范围。
list6由于泛型类型的范围超过了 test1的形参范围,因而编译器报错。
Java中的泛型