有才华的人,别忘记给滋润你的那块土壤施肥

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  28 随笔 :: 5 文章 :: 147 评论 :: 0 Trackbacks

因为公司的程序要兼容到JDK1.3,所以对泛型没有系统的去了解下。以下是在核心技术那本书上的摘抄:
使用泛型机制编写的程序代码要比那些杂乱地使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。如:

ArrayList<Sting> files = new ArrayList<String>();

一看就知道这个数组列表中包含的是String对象。同时编译器据此不需要强制类型转换,返回类型为String,而不是Object:

String file = files.get(0);

同时当files调用add方法,编译器知道有一个类型是String的参数。这会比使用Object参数更安全,编译器可以进行检查,避免错误类型的对象。
泛型类:具有一个或多个类型变量的类。如下面Pair类的代码:

public class Pair<T>{
  
private T first;
  
private T second;
  
public Pair(){
   
this.first = null;
   
this.second = null;
  }

  
public Pair(T first, T second){
   
this.first = first;
   
this.second = second;
  }

  
public T getFirst() {
   
return first;
  }

  
public void setFirst(T first) {
   
this.first = first;
  }

  
public T getSecond() {
   
return second;
  }

  
public void setSecond(T second) {
   
this.second = second;
  }

}

当构造函数两个域不同类型:

Public class Pair<T,U>{……}

补充:类型变量使用大写形式,且较短,如使用E表示集合的元素类型,K和V表示表的关键字与值的类型,T表示任意类型。
泛型方法:定义一个带有类型参数的简单方法。

class GenericTest{
 
public static<T> T getMiddle(T[] a){
  
return a[a.length/2];
 }

}

泛型方法可以在普通的类中,也可以在泛型类中。当调用一个泛型方法时,
方法名前的尖括号中放入具体的类型:

String[] names = {"a","b","c"};
String  middle 
= GenericTest.<String>getMiddle(names);

但是在大多数情况下,方法调用中可以省略<String>类型参数。
类型变量的限定:
如下代码,我们要计算数组中最小元素:

   static class GenericTest{
  
public static<T> T getMin(T[] a){
   
if(a == null || a.length  == 0){
    
return null;
   }

   T smallest 
= a[0];
   
for(int i=1; i<a.length;i++){
    
if(smallest.compareTo(a[i]) >0 )
     smallest 
= a[i];
   }

   
return smallest;
  }

 }

如此如何知道T所属的类有compareTo方法呢?,可以将T限制为实现Comparable接口的类,如:

public static<extends Comparable> T getMin(T[] a){。。。}

应此没有实现Comparable接口,调用getMin将会产生一个编译错误。
一个类型变量或通配符可以有多个限定,如:

<extends Comparable & Serializable>

泛型代码和虚拟机
1. 虚拟机中没有泛型,只有普通的类和方法;
2. 所有的类型参数都用他们的边界替换;
3. 桥方法被合成为保持多态的;
4. 为保持类型的安全性,必要时插入强制类型转换。

约束与局限性
1、 基本类型:不能用类型参数替换基本类型。因此没有Pair<double>,只有Pair<Double>,原因是类型擦除之后Pair类具有Object类型的域,而Object不能存储double值。
2、 运行时类型查询:虚拟机中的对象总有一个特定的非泛型类型,所以所有的类型查询只产生原始类型。所以无论何时使用instanceof或设计类型的强制类型转换表达式都会看到一个编译警告。同样getClass方法总是返回原始类型。
3、 异常:不能抛出也不能捕获泛型类的对象泛型无法扩展Throwable都不合法。如:

public class Problem<T> extends Exception{…..}//错误,

不能在catch子句中使用类型变量。但是在异常声明中可以使用类型变量。如:

      public<extends Throwable> void test(Class<T> a){
           
try{  
           }
catch(Throwable e){  
          }

      }
//可以通过

4、 数组:不能声明参数化类型的数组
5、 泛型类型的实例化:不能实例化泛型,如下面就是错误的:

public class Pair<T>{
 
public Pair(){
  
this.first = new T();
  
this.second = new T();
  }

}

6、不能在静态域或方法中引用类型变量。如下面的高招将无法实施:

public class Singleton<T>{
          
private static T singleInstance;//错误
          public static T getSingleInstance(){//错误
      if(singleInstance != null)
    
return singleInstance;
          }

 }

7、擦除后的冲突:要支持擦除的转换,需要强行限制一个类或类型变量不能同时成为两个接口类型的子类,而这个接口是同一接口的不同参数化。

 

posted on 2008-04-10 16:24 kissjava 阅读(707) 评论(0)  编辑  收藏 所属分类: java基础

只有注册用户登录后才能发表评论。


网站导航: