熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Javascript >> 正文

J2SE5.0新特性示例---泛型

2013-11-23 17:55:07  來源: Javascript 

  簡介

  泛型其實並不是一種新的語言元素C++中早就就有但是在C++之後的java卻沒有吸收這個特性現在Java也有了泛型的特性大概也和Net的競爭有關系吧

  首先看泛型的一個應用

  在過去我們可能經常要寫一些類似這樣的代碼

  

  List stringList=new LinkedList();
stringListadd(firstString);
stringListadd(secondString);
String str=(String)erator()next();

  實際上第三行對String的類型轉換意義並不大因為通常我們如果在操作一個List都是知道這個List裡面放的是什麼類型對象的但是我們如果不這樣寫又通不過語法檢查

  利用java的泛型機制我們可以這麼寫

  

  List<String> stringList=new LinkedList<String>();
stringListadd(firstString);
stringListadd(secondString);
String str=erator()next();

  這樣做的好處是在定義容器的時候就指明了容器中的類型一方面我們不再需要取一個元素時候做強制類型轉換另外一方面如果在這個容器中放入的對象類型不符合要求那麼會在編譯時候產生一個錯誤而不是在運行時候才拋出一個異常

  另外這樣也提高了程序的可讀性

  泛型類型的定義

  下面是一個簡單的使用泛型類的定義

  

  public class MyGenericClass<T> {
    private T value;

  public T getValue() {
       return value;
    }

  public void setValue(T value) {
       thisvalue = value;
    }
}

  值得注意的一點是靜態變量不能夠使用泛型定義也就是說類似下面的語句是非法的

   public class MyGenericClass<T> {
    public static T value;//錯誤的定義
}

  此外泛型的定義不會被繼承舉個例子來說如果A是B的子類而C是一個聲明了泛型定義的類型的話C<A>不是C<B>的子類為了更好的說明可以看下面的代碼這段代碼是錯誤的

   List<String> strList =new ArrayList<String>();
List<Object> objList=strList;  //錯誤的賦值

  不過這樣一段代碼是正確的

   List<Object> strList =new ArrayList<Object>();
strListadd(a string);

  統配類型

  假設我們需要這樣一個函數使用它可以把一個集合中所有的元素打印出來在以前我們可能這樣定義

   void printCollection(Collection c) {
    Iterator i = erator();
    for (k = ; k < csize(); k++)
    {
       Systemoutprintln(inext());
    }
}

  使用新的泛型特性我們可以這樣寫

   void printCollection(Collection<Object> c)
{
    for (Object e : c)
    {
       Systemoutprintln(e);
    }
}

  但是這樣有一個問題假如我們現在有個對象類型是Collection<String>那麼我們不能夠將它作為參數傳給printCollection因為Collection<String>並不是Collection<Object>的子類

  為了解決這個問題我們可以使用統配類型?也就是定義成下面這個樣子

   void printCollection(Collection<?> c)
{
    for (Object e : c)
    {
       Systemoutprintln(e);
    }
}

  可以說Collection<?>是所有Collection的父類

  再來看一段下面的代碼

   private void clearAllMaps(Collection<Map> c)
{
       for(Map m:c)
       {
           mclear();
       }
}

  毫無疑問它也存在上面我們所說的問題也就是對HashMap之類Map的子類無法進行操作但是如果我們將參數改成Collection<?>又不大合理因為我們只希望對父類為Map的子類進行操作那麼我們可以這樣改寫

   private void clearAllMaps(Collection<? extends Map> c)
{
    for(Map m:c)
    {
       mclear();
    }
}

  類似於? extends Map之類的統配符稱為限定統配類型

  假設一個對象h類型為Collection<HashMap>那麼我們將h作為參數傳給clearAllMaps如下面一段代碼所示

   List<HashMap<StringString>> h=new ArrayList<HashMap<StringString>>();
HashMap<StringString> m=new HashMap<StringString>();
mput(keyvalue);
hadd(m);
clearAllMaps(h);

  對於在類似於上面所說使用了? extend XXX的方法值得注意的一點是不能夠在方法體內用XXX的子類對象作為代替如下面一段代碼是錯誤的

   public void addRectangle(List<? extends Shape> shapes)
{
    shapesadd( new Rectangle()); // 錯誤用法!
}

  這裡我們假設Rectangle是Shape的一個子類

  不允許這樣寫的原因比較簡單因為調用該方法時候參數類型可能是Shape的另外一個子類假如說Shape除了Rectangle這個子類以外還有另外一個子類Circle那麼我們可以把一個List<Circle>類型的對象作為參數傳給這個方法(注意這樣是合法的)而在方法體內卻把一個Rectangle對象放到了shapes裡面這顯然是不合理的

  除了extends在泛型參數類型中還可以使用super關鍵字參照下面一段程序

private void addString(Collection <? super String> c)
{
       cadd(a String);
}

  泛型函數

  我們在前面提到了統配類型現在讓我們來設想一個函數它實現這樣的功能將一個數組中的元素添加到一個Collection中為了保證程序的通用性我們可能會寫出另外一段錯誤的代碼

   private void fromArrayToCollection(Object[] a Collection<?> c)
{
    for (Object o : a)
    {
       cadd(o); // 錯誤的代碼
    }
}

  那麼這個函數應該怎麼寫呢?我們可以通過對函數添加泛型參數的方法實現如下面所示

   private <T> void  exfromArrayToCollection(T[] a  Collection<T> c)
{
       for (T o : a)
       {
           cadd(o); //這樣是正確的
       }
}

  那麼在什麼時候我們應該使用統配類型什麼時候我們應該使用泛型函數呢?答案是取決於函數參數之間函數參數和返回值之間的類型依賴性

  如果一個函數的參數類型與函數返回的參數沒有必然關聯同時對於該函數其他的參數的類型也沒有依賴關系那麼我們就應該使用統配符否則就應該使用泛型函數

  為了更清楚地說明這一點我們可以看一下javautil包中Collections類型幾個方法的定義

   class Collections {
    static void swap(List<?> list int i int j) {}
    static <T> void  copy                                 (List<? super T> dest List<? extends T> src)    {}
}

  其中swap函數實際上也可以這樣定義

   static <T>void swap(List<T> list int i int j) {}

  但是注意到這裡泛型類型參數T只在參數中用到了一次也就是說它和函數其他部分沒有依賴性這可以看作是我們應該使用?的一個標志

  copy方法中拷貝源src中的元素必須是dest所能夠接受的src中的元素必須是T的一個子類但是具體它是哪種子類我們又不必關心所以方法中使用了泛型作為一個類型參數同時也用了統配類型作為第二類型參數


From:http://tw.wingwit.com/Article/program/Java/Javascript/201311/25360.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.