1.泛型的概念.
泛型英文名为(Generic Type),从字面上就是通用化,一般化了的类型.
类似于类是对象的一种抽象,泛型可以说就是对类进行抽象.
2.泛型的语法
  • 类型参数的形式化
  • 在java5中利用<E>这样的语法来定义形式化类型参数.
    public interface List<E> {
               void add(E x);
               Iterator<E> iterator();
    }
    

    以上代码中E就代表了一个形式化类型参数
  • 类型参数的实际化
  • List<Integer> myIntList = new LinkedList<Integer>();
    Integer x = myIntList.iterator().next();
    

    上述代码是java5以后经常看到的声明只能放某种对象的list,以用于加强编译器的类型安全检查.
    并且在取出list中的元素时也不需要进行强制的类型转化.

3.泛型的种类
  • 在类中声明的泛型
  • public interface List<E> {
               void add(E x);
               Iterator<E> iterator();
    }
    

    上面代码中的E就可以到作一个类来用,可以用于声明函数的参数(E x),也可以继续当作形式化类型参数传给其他泛型的声明(Iterator<E>)
  • 泛型化的方法
  •    static <T> void fromArrayToCollection(T[] a, Collection<T> c){
           for (T o : a) {
               c.add(o); // correct
           }
        }
    

    以上定义中的<T>定义了方法的形式化类型参数,该类型参数可以和类中定义的类型参数一起使用,但是该参数只能方法体的范围类有效.
    public class TestGeneric<E>
    {
    	public <T> void testOfMethodGeneric(T t,E e)
    	{
    		System.out.print(t);
    		System.out.print(e);
    	}
    }
    


4.通配符和继承
  • 除了形式化类型参数的声明,其他地方都可以使用通配符.
  •         List<?> testList = new ArrayList<String>();
    	public void testOfWildCard(List<?> list)
    	{
    		
    	}
    

    ?的语义是表示任意的类型.List<?>就表示可以接受任何类型数据的集合,但是这样用一个限制就是不能往集合中插入任何元素(除了null,因为null是所有类型的成员),因为编译器也不知道集合中的元素类型是什么.
  • 通配符可以加入上下限的限制.
  • <? extends Father>表示匹配所有继承自father的类型(包括father,son,grand child等).
    <? super Father>表示匹配所有Father所继承的类型(包括father,grandpa,grandma等).
  • 通配符的用意
  • List<String> ls = new ArrayList<String>(); //1
    //由于定义泛型的时候并没有使用通配符,会导致编译期的类型转化错误.具体原因请看后续代码
    List<Object> lo = ls; //2
    lo.add(new Object()); // 3
    String s = ls.get(0); // 4: 试图把Object赋值给String
    

    有了通配符,在泛型使用的时候对子类类继承的功能就可以扩展.
    但是给人感觉这个可能是因为编译器处理不了,结果我们就非得要手动声明.

5.使用要点
  • 泛型类是共享(实际上的意思就是泛型类中的形式化类型参数是与泛型类的某个实际对象绑定的,不能在泛型类的static语义的代码断中调用形式化类型参数
  •        
           List<String> l1 = new ArrayList<String>();
           List<Integer> l2 = new ArrayList<Integer>();
           System.out.println(l1.getClass() == l2.getClass())//true
    

    public class TestClient<E>{
    	private static E e;//编译错误提示静态不能应用非静态内容.
    	private E e1;//可以通过
    }

    进一步推论可以得出一个结论如下代码也是没有意义的
           Collection cs = new ArrayList<String>();
           //下面这句话是没有意义的从编译器得到的错误信息感觉由于
           泛型化的信息只在编译器有效,运行期被擦除了,导致运行期间根本就没有Collection<String>这样一个类.
           if (cs instanceof Collection<String>) { ...} // 
    
  • 除了数组其他对象都嵌套的使用形式化类型参数定义.
  • List<String>[] lsa = new List<String>[10]; // not really allowed

    以上定义是非法的
  • Class对象的泛型化
  • java5中Class类的声明带有一个类型参数T其用途如下
    String.class类型代表 Class<String>
    Collection<EmpInfo> emps=sqlUtility.select(EmpInfo.class, ”select * from emps”); 
    public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
    Collection<T> result = new ArrayList<T>();
    /* run sql query using jdbc */
    for ( /* iterate over jdbc results */ ) {
    T item = c.newInstance();
    /* use reflection and set all of item’s fields from sql results */
    result.add(item);
    }
    return result;
    }

    以上的写法实际就是简化了select方法中关于实际类的创建的部分,至少保证了类必须存在,但是在方法和字段级别还是需要利用反射来解决.
  • 另外泛型的代码还支持&符号
  • public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

    相当于
    public static Comparable max(Collection coll)
    public static Object max(Collection coll)
    的并集
    


之所以去研究了一下泛型是以为在看struts2中ioc框架的源码的过程中发现有很多泛型的内容看不懂所以特地研究了一下.
看完了以后对于泛型总体感觉并没有说为开发带来多少便利,只是加强了对编译器类型的检查.
评论
发表评论

您还没有登录,请登录后发表评论

myoldman
  • 浏览: 6273 次
  • 性别: Icon_minigender_1
  • 来自: 福建福州
  • 详细资料
搜索本博客
存档
最新评论