首页 > 代码库 > 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中的泛型