国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

J2SE5.0 實例---泛型

2024-07-21 02:14:11
字體:
來源:轉載
供稿:網友
泛型簡介


泛型其實并不是一種新的語言元素,c++中早就就有,但是在c++之后的java卻沒有吸收這個特性,現在java也有了泛型的特性,大概也和.net的競爭有關系吧。

首先看泛型的一個應用。

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

list stringlist=new linkedlist();

stringlist.add("firststring");

stringlist.add("secondstring");

string str=(string)stringlist.iterator().next();



實際上第三行對string的類型轉換意義并不大,因為通常我們如果在操作一個list,都是知道這個list里面放的是什么類型對象的,但是我們如果不這樣寫又通不過語法檢查。

利用java的泛型機制,我們可以這么寫:

list<string> stringlist=new linkedlist<string>();

stringlist.add("firststring");

stringlist.add("secondstring");

string str=stringlist.iterator().next();

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

另外這樣也提高了程序的可讀性。
泛型類型的定義
下面是一個簡單的使用泛型類的定義:

public class mygenericclass<t> {

  private t value;


 


  public t getvalue() {

     return value;

  }

 

  public void setvalue(t value) {

     this.value = 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>();

strlist.add("jsdkfjsdl");
統配類型
假設我們需要這樣一個函數,使用它可以把一個集合中所有的元素打印出來,在以前我們可能這樣定義:

void printcollection(collection c) {

  iterator i = c.iterator();

  for (k = 0; k < c.size(); k++)

  {

     system.out.println(i.next());

  }

}

使用新的泛型特性我們可能會這樣寫:

void printcollection(collection<object> c)

{

  for (object e : c)

  {

     system.out.println(e);

  }

}

但是這樣有一個問題,假如我們現在有個對象類型是collection<string>,那么我們不能夠將它作為參數傳給printcollection,因為collection<string>并不是collection<object>的子類。

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

void printcollection(collection<?> c)

{

  for (object e : c)

  {

     system.out.println(e);

  }

}

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

再來看一段下面的代碼

private void clearallmaps(collection<map> c)

{

     for(map m:c)

     {

         m.clear();

     }

}

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

private void clearallmaps(collection<? extends map> c)

{

  for(map m:c)

  {

     m.clear();

  }

}

類似于? extends map之類的統配符稱為限定統配類型。

假設一個對象h類型為collection<hashmap>,那么我們將h作為參數傳給clearallmaps,如下面一段代碼所示:

list<hashmap<string,string>> h=new arraylist<hashmap<string,string>>();

hashmap<string,string> m=new hashmap<string,string>();

m.put("key","value");

h.add(m);

clearallmaps(h);

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

public void addrectangle(list<? extends shape> shapes)

{

        shapes.add(0, new rectangle()); // 錯誤用法!

}

這里我們假設rectangle是shape的一個子類。

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

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

private void addstring(collection <? super string> c)

{

         c.add("a string");

}


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

private void fromarraytocollection(object[] a, collection<?> c)

{

        for (object o : a)

        {

         c.add(o); // 錯誤的代碼

        }

}

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

private <t> void  exfromarraytocollection(t[] a,  collection<t> c)

{

         for (t o : a)

         {

            c.add(o); //這樣是正確的

         }

}


 


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

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

為了更清楚地說明這一點,我們可以看一下java.util包中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的一個子類,但是具體它是哪種子類我們又不必關心,所以方法中使用了泛型作為一個類型參數,同時也用了統配類型作為第二類型參數
  • 本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。
  • 上一篇:Threads

    下一篇:hibernate in 查詢

    發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 阿合奇县| 遵义市| 东山县| 禄劝| 洪洞县| 巴彦县| 呼伦贝尔市| 土默特右旗| 饶平县| 喀喇沁旗| 金阳县| 天柱县| 临汾市| 民县| 延安市| 漠河县| 凤台县| 古丈县| 通城县| 浪卡子县| 黑山县| 关岭| 庆城县| 璧山县| 汶上县| 南京市| 民乐县| 灌云县| 文安县| 额尔古纳市| 三门县| 宽甸| 台州市| 临泉县| 攀枝花市| 钟山县| 永新县| 鸡东县| 贵港市| 沭阳县| 巫山县|