Java泛型

来源:互联网 发布:童装代理一手货源淘宝 编辑:程序博客网 时间:2024/05/18 22:51
  1. 泛型的主要功能是提供编译时类型检查,原生态类型(即不使用泛型)躲避了编译时类型检查,不推荐使用,在IDE中编辑时会有警告。
  2. 泛型有子类化(subtyping)规则。参数化类型的List<String>是原生态类型List的一个子类型,但不是参数化类型List<Object>的子类型。在泛型中不承认参数之间的继承关系。但是ArrayList<Object>是List<Object>的子类。与泛型刚好相反,数组是协变(covariant)的,即Sub为Super的子类时,Sub[]就是Super[]的子类。创建泛型数组是非法的,比如new List<E>[]、new List<String>[]、new E[]都是非法的,但是new Stack<int[]>是合法的。
  3. 无限制的通配符类型。如果不确定或不关心实际的类型参数,就可用一个?代替,如List<?>,使用无限制的通配符类型在IDE中不会有警告。
  4. 在类文字(class literal)中必须使用原生态类型,List.class,String[].class,int.class都是合法的,List<String>.class,List<?>.class是不合法的。List<String>和List<Integer>共用一个Class对象,即List.class。
  5. 泛型信息在运行时被擦除。下面是利用泛型来使用instanceof的首先方法:
    if(o instanceof Set){Set<?> m=(Set<?>)o;//......}
    instanceof是在运行时决定的,而泛型信息在运行时被擦除,所以此时要使用原生态的Set。把o转变成通配符类型Set<?>,这是个受检查的(checked)转换,因此不会导致编译时警告。
  6. 当无法消除警告,而我们又可以保证代码是类型安全时,可以用一个@SuppressWarnings("unchecked")注解来禁止这些警告,同时加一条注释,说明为什么这么做是安全的。SuppressWarnings可以用在任何粒度的级别中,从单独的局部变量声明到整个类都可以,当然应该在尽可能小的范围内使用。
  7. 泛型类类似于C++中的模板类。
    public class Stack<E> {private E[] eles;private int size=0;private static final int DEFAULT_INITIAL_CAPACITY=16;@SuppressWarnings("unchecked")public Stack(){//定义构造函数时不需要使用参数标记//eles=new E[DEFAULT_INITIAL_CAPACITY];错误。不能创建不可具化(non-reifiable)的类型数组。eles=(E[])new Object[DEFAULT_INITIAL_CAPACITY];//编译器不能保证你的强制转换是类型安全的,所以要使用SuppressWarnings}public void push(E e){ensureCapacity();eles[size++]=e;}public E pop(){if(size==0)throw new EmptyStackException();E result=eles[--size];eles[size]=null;//类自己管理内在时记得要及时释放内在,免得内在泄漏return result;}private void ensureCapacity(){if(eles.length==size)eles=Arrays.copyOf(eles, 2*size+1);}}
  8. 泛型中的参数不能是基本数据类型。Stack<int>是错误的。
  9. 泛型方法。
    public static <E> Set<E> union(Set<E> s1,Set<E> s2){Set<E> result=new HashSet<E>(s1);result.addAll(s2);return result;}
    静态工厂方法尤其适合泛型化。
    比如Map<String,List<String>> var=new HashMap<String,List<String>>();类型出现在等号两边显得有些冗余。如果Map定义了如下使用了泛型的静态工厂方法
    public static <K,V> HashMap<K,V> newHashMap(){return new HashMap<K,V>();}
    那么用Map的这个静态工厂方法创建对象代码就比较简洁了:
    Map <String,List<String>> var=newHashMap();
  10. <E extends Number>、<T extends Comparable<T>>、List<? extends Number>、static <E> List<E> asList(E[] a)都是可以的。
  11. 区别<? extends T>和<? suprt T>。如果参数化类型表示一个T生产者,就用<? extends T>,如果表示一个T消费者,就用<? suprt T>。
  12. 类的类型从字面上看不是简单的Class,而是Class<T>,比如String.class属于Class<String>类型,Integer.class属于Class<Integer>类型。
    public class Favorites {private Map<Class<?>,Object> favorites=new HashMap<Class<?>,Object>();public <T> void putFavorite(Class<T> type,T instance){if(type==null)throw new NullPointerException("Type is null");favorites.put(type, instance);}public <T> T getFavorite(Class<T> type){return type.cast(favorites.get(type));     //利用CLass的cast方法,将对象引用}public static void main(String[] args){Favorites f=new Favorites();f.putFavorite(Integer.class, 2);f.putFavorite(Class.class,Favorites.class);int i=f.getFavorite(Integer.class);Class<?> c=f.getFavorite(Class.class);System.out.printf("%d\t%s\n",i,c.getName());}}
    输出:2 general.Favorites
    上述代码中的Map的key值可以是String或者String[],但不能是List<String>,因为List<String>.class是语法错误。





原创粉丝点击