Java泛型

jopen 5年前

一 定义
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

二 泛型作用
1)提高的代码的复用性
2)泛型提供了类型检查,减少了数据的类型转换
3)保证了类型安全
例如下面这段代码,会抛出ClassCastException异常

List list = new ArrayList();  list.add("abc");  list.add(new Integer(1));//可以通过编译  for (Object object : list) {      System.out.println((String)object);//抛出ClassCastException异常  }

使用泛型后则避免这种情况发生

List<String> list = new ArrayList<String>();  list.add("abc");  //list.add(new Integer(1));//编译器类型检查,不能通过编译  for (String string : list) {      System.out.println(string);//无需强制类型转换  }

注意,不能在泛型中添加其它类型

public static <T> void fromArrayToCollection(T[] a,Collection<T> c){      for (T t : a) {          c.add(t);          //c.add(new Object());  //编译错误      }  }

三 泛型边界
作用:
1)确保泛型类型只能是某一部分类型,比如操作数据的时候,你会希望是Number或其子类类型
2)可以调用该类型方法,Java为了兼容前面的版本,泛型的实现是通过类型擦除来实现的,使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉,在生成的Java字节代码中是不包含泛型中的类型信息的。这个过程就称为类型擦除。如在代码中定义的List<Object>和List<String>等类型,在编译之后都会变成List。System.out.println(new ArrayList<String>().getClass()==new ArrayList<Integer>().getClass());//true
对于如下方法,如果传入一个String,想在test方法中里面调用String.equals方法则无法实现

public void test(T t){      t.equals("");//error  }

加入边界后,则可以:

class Hasf{      public void f();  }  public <T extends Hasf> void test(T t){      t.f();  }

注意:边界也可以有多个,用class D <T extends A&B&C>{} 限制范围中最多有一个类。如果用一个类作为限定,它必须是限定列表中的第一个。

四 泛型继承
看如下方法

public void test(List<Object> list);

如果传入一个List<String>,则编译会出错。尽管String是Object的子类,但List<String>不是List<Object>的子类,也就是说,无论类A与类B是否存在关联,MyClass<A>与MyClass<B>都没有任何关联。
但因为List<E> extends Collection<E>,
所以List<Object>则是Collection<Object>的子类型,ArrayList<Object>就是List<Object>的子类型,所以test中可以传入ArrayList<Object>

五 通配符
在声明泛型(给泛型赋值)时,既可以指定一个具体的类型,如List<String>就声明了具体的类型是String;也可以用通配符?来表示未知类型,如List<?>就声明了List中包含的元素类型是未知的。?号解决java泛型中List<String> 不是List<Object>子类的问题

public static void doTest(List<Parent>list){}  public static void doTest1(List<? extends Parent> list){      //不能为list添加非null数据  }  class Parent{}  class Child extends Parent{  }  public static void main(String[] args){      List <Parent>parentList=new ArrayList<Parent>();      List <Child>childList=new ArrayList<Child>();      doTest1(parentList);      doTest1(childList); // 如果是doTest(childList);的话,这里编译错误   }