Java泛型
一 定义
泛型是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);的话,这里编译错误 }