1. 程式人生 > >java之泛型的應用

java之泛型的應用

泛型(Generic)—泛形的作用

JDK5以前,物件儲存到集合中就會失去其特性,取出時通常要程式設計師手工進行型別的強制轉換,這樣不可避免就會引發程式的一些安全性問題。例如:

ArrayList list = new ArrayList();

list.add("abc");

Integer num = (Integer) list.get(0);  //執行時會出錯,但編碼時發現不了

list.add(new Random());

list.add(new ArrayList());

for(int i=0;i<list.size();i++){

(?)list.get(i);          //此處取出來的物件應轉換成什麼型別

}

JDK5中的泛形允許程式設計師在編寫集合程式碼時,就限制集合的處理型別,從而把原來程式執行時可能發生問題,轉變為編譯時的問題,以此提高程式的可讀性和穩定性(尤其在大型程式中更為突出)

注意:泛型是提供給javac編譯器使用的,它用於限定集合的輸入型別,讓編譯器在原始碼級別上,即擋住向集合中插入非法資料。但編譯器編譯完帶有泛形的java程式後,生成的class檔案中將不再帶有泛形資訊,以此使程式執行效率不受到影響,這個過程稱之為擦除

泛形的基本術語,以ArrayList<E>為例:<>念著typeof

ArrayList<E>中的E稱為型別引數變數

ArrayList<Integer>中的Integer稱為實際型別引數

整個稱為ArrayList<E>泛型型別

整個ArrayList<Integer>稱為引數化的型別ParameterizedType 

泛型典型應用:

使用迭代器迭代泛形集合中的元素。

使用增強for迴圈迭代泛形集合中的元素。

存取HashMap中的元素。

//使用迭代器迭代泛型集合中的元素。

@Test

Public void test2(){

List<Integer> list=new ArrayList<Integer>();

 list.add(1);

 list.add(2);

 list.add(3);

Iterator<Integer> it=list.iterator();

While (it.hasNext()){

System.out.println(it.next());

}

}

//使用增強for迴圈迭代泛型集合中的元素

@Test

Public void test3(){

List<Integer> list=new ArrayList<Integer>();

 list.add(1);

 list.add(2);

 list.add(3);

For(Integer  i:list){

System.out.println(i);

}

}

//存取HashMap中的元素。

@Test

Public void test4(){

Map<String,Integer> map=new HashMap<String,Integer>();

map.put(“key01”,1);

map.put(“key01”,1);

map.put(“key01”,1);

//(“key01”,1)看成一個Map.Entry<String,Integer>

Set<Map.Entry<String,Integer>> set=map.entrySet();

For(Map.Entry<String,Integer> en:set){

System.out.println(en.getKey()+”...”+en.getValue());

}

}

注意

使用泛形時的幾個常見問題:

使用泛形時,泛形型別須為引用型別,不能是基本資料型別

ArrayList<String> list = new ArrayList<Object>();  //

ArrayList<Object> list = new ArrayList<String>(); //

ArrayList<String> list = new ArrayList ();               //

ArrayList list = new ArrayList<String>();               //

:使用泛型

        *  兩邊的型別必須一致

              ArrayList<String> list = new ArrayList<String>();

        *  兩邊只有一邊用泛型(為了保持相容性)

              ArrayList<String> list = new ArrayList ();

              ArrayList list = new ArrayList<String>();

自定義泛形——泛型方法:

Java程式中的普通方法、構造方法和靜態方法中都可以使用泛型。方法使用泛形前,必須對泛形進行宣告,語法:<T> T可以是任意字母,但通常必須要大寫。<T>通常需放在方法的返回值宣告之前。例如:

public static <T> void method(T t);

注意:

只有物件型別才能作為泛型方法的實際引數。

在泛型中可以同時有多個型別,例如:編寫一個泛形方法,實現陣列元素的交換。

編寫一個泛形方法,接收一個任意陣列,並顛倒陣列中的所有元素

如果一個類多處都要用到同一個泛型,這時可以把泛形定義在類上(即類級別的泛型),語法格式如下:

public class GenericDao<T> {

private T field1;

public void save(T obj){}

public T getId(int id){}

}

注意

    *  在類級別上定義的泛型,只對類的非靜態成員有效

    *  靜態方法不能使用類定義的泛形,而應單獨定義泛形。

/*

 *  類級別泛型

 *  在類級別上定義的泛型,只對類的非靜態成員有效

 */

Public class DemoClass3<T>{

Public void mathod1(T  t){

}

Public void mathod2(T  t){

}

//靜態方法不能使用類定義的泛型,而應單獨定義泛型

Public static <T> void method3(T  t){

}

}

泛形的典型應用:BaseDao

泛型的高階應用——萬用字元:

定義一個方法,接收一個集合,並打印出集合中的所有元素,如下所示:

void print (Collection<String> c) {

           for (String e : c) {

                 System.out.println(e);

           }

問題:該方法只能列印儲存了String物件的集合,不能列印其它集合。萬用字元用於解決此類問題,方法的定義可改寫為如下形式:

void print (Collection<?> c)  {//Collection<?>(發音為:"collection of unknown") 

for (Object  e : c) {

System.out.println(e);

}

}

此種形式下需要注意的是:由於print方法c引數的型別為Collection<?>,即表示一種不確定的型別,因此在方法體內不能呼叫與型別相關的方法,例如add()方法。

       但可以呼叫與型別無關的方法,例如size()方法

總結:使用?萬用字元主要用於引用物件,使用了?萬用字元,就只能調物件與型別無關的方法,不能呼叫物件與型別有關的方法。

限定萬用字元的上邊界(?的型別必須是Number的子類)

限定萬用字元總是包括自己。

正確:Vector<? extends Number> x = new Vector<Integer>();

錯誤:Vector<? extends Number> x = new Vector<String>();

限定萬用字元的下邊界(?的型別必須是Integer的父類)

正確:Vector<? super Integer> x = new Vector<Number>();

錯誤:Vector<? super Integer> x = new Vector<Byte>();

問題:以下程式碼行不行?(如果是Byte型別不可以)

public void add(List<? extends Number> list){

list.add(1000);

}

相關推薦

java應用

泛型(Generic)—泛形的作用 JDK5以前,物件儲存到集合中就會失去其特性,取出時通常要程式設計師手工進行型別的強制轉換,這樣不可避免就會引發程式的一些安全性問題。例如: ArrayList list = new ArrayList(); list.add("abc"); Integer num =

java

一次 數據 addall sta AC 必須 推薦 string ext 1 /* 2 * a. 泛型的好處 3 * 提高安全性(將運行期的錯誤轉換到編譯期) 4 * 省去強制類型轉換的麻煩 5

Java基礎知識(JAVA

書寫 來源 bject tail java基礎 包括 知識 為什麽 情況下 什麽是泛型?為什麽要使用泛型? 泛型,即“參數化類型”。一提到參數,最熟悉的就是定義方法時有形參,然後調用此方法時傳遞實參。那麽參數化類型怎麽理解呢?顧名

【一天一個基礎系列】- java

### 簡介 + 說起各種高階語言,不得不談泛型,當我們在使用java集合的時候,會發現集合有個缺點:把一個物件“丟進”集合之後,集合就會“忘記”這個物件的資料型別,當再次取出該物件時,改物件的編譯型別就變成了`Object`型別 + 問題1:集合對元素型別沒有任何限制,這樣可能會引發一些問題,比如建立一個

Java應用打造Android中ListView和GridView萬能介面卡【CommonAdapter】--超簡潔寫法

在android中使用最多的就是ListView,GridView,用到這兩個控制元件那麼肯定要用到介面卡,那就是定義一個類繼承BaseAdapter,讓後覆寫它裡面的getCount()

java核心卷軸程序設計

== ext generic 原始類型 檢查 equals 綁定 () 應該   本文根據《Java核心卷軸》第十二章總結而來,更加詳細的內容請查看《Java核心卷軸》 1. 泛型類型只能是引用類型,不可以使用基本數據類型。 2. 類型變量含義    E : 集合

java的一些知識點:Java--應用--接口、方法、數組、嵌套

泛型數組 light inf 返回值 通過 類實例化 this str set 感謝這位大神: http://blog.csdn.net/waldmer/article/details/12773021 1、泛型接口 1.1泛型接口的基本概念 1.2泛型接口實現的兩

201671010128 2017-10-30《Java程序設計》程序設計

amd 進度 第六周 進度條 ray 數量 返回 不同 概念 一、基本概念 泛型也被稱為參數化類型(parameterized type),就是在定義類、接口和方法時,通過類型參數指示將要處理的對象類型。(如ArrayList類) 泛型程序設計(Generic progr

14. Java基礎

remove 角度 分享 The 兩個 -a 類型形參 建議 set 引用自:https://www.cnblogs.com/lwbqqyumidi/p/3837629.html , https://blog.csdn.net/s10461/article/details/

Java核心技術

泛型類(generic class)是帶有一個或者多個型別形參(type parameter)的類。 泛型方法是帶有型別形參的方法。 可以要求型別形參必須是一個或多個型別的子型別。 泛型類不是協變的(invariant):當S是T的子型別時,G<S>

Java系列

自從 JDK 1.5 提供了泛型概念,泛型使得開發者可以定義較為安全的型別,不至於強制型別轉化時出現型別轉化異常,在沒有反省之前,可以通過 Object 來完成不同型別資料之間的操作,但是強制型別轉換(向下轉型)在不確定具體型別的情況下會出錯,泛型機制的引入就是解決資料型別不明確 的問題

java遺珠型別推斷

型別推斷 型別推斷是java編譯器的一種能力,通過檢視方法呼叫和相應的宣告來決定什麼樣的型別引數或者引數是更為合理的呼叫。 推斷演算法先確定引數的型別,分配結果或者返回的型別,最終推斷演算法查詢適合所有引數最適合的型別。 為了說明這點,來看下面的例子: publ

java遺珠萬用字元

我們在之前說過明確指定了泛型型別的引數之後,會把引數限制的很嚴格,萬用字元的作用就是放寬這種限制,有上限有界萬用字元<? extends A>,下限有界萬用字元<? extends B>,無界萬用字元<?>。上限有界和無界經常

java遺珠型別擦除

擦除規則 泛型的作用之前已經介紹過了只是用於編譯之前更為嚴格的型別檢查,其他的一些特性也都是編譯之前的,在編譯之後泛型是會被擦除掉的。 型別擦除所做的事情如下: 如果是無界限的則會把型別引數替換成Object,如果是有界限的則會把型別引數替換為界限型別。 插入

JAVA應用,太好使了

@Override public int insertBatch(List<SCT> list,String filename) { int result=0; try{ i

java邊界

在網上發現這篇文章寫得不錯,地址:http://build.cthuwork.com:8081/wordpress/category/java教程/java再談泛型/ 首先本文假定讀者對Java的泛型有基礎的瞭解,若需要請參考其他資料配合閱讀。 泛型的泛參(type argu

黑馬程式設計師——Java集合框架(二)

培訓、java培訓、java學習型技術部落格、期待與您交流!------------               泛型 一、泛型概述 1.什麼是泛型? 泛型就是指將資料型別引數化,把以前固定的資料型別用一個代表資料型別的引數進行表示,該引數可以接受傳入的任意資料型別。可以這

java應用詳解

在平時的開發過程中,很多哥們不清楚泛型的概念以及用法,所以很多時候,寫了很多沒必要的程式碼,又或者,看到別人在使用泛型的時候,感覺對方很牛逼。。。 其實,泛型沒你想象的那麼難,follow me一、為什麼要使用泛型 我們來看個簡單的例項 public class Test {  

Java SE7新特性例項建立時的型別推斷

只要編譯器從上下文中能夠推斷出型別引數,你就可以使用一個空的型別引數集合 (<>)代替呼叫一個泛型類的構造器所需要的型別引數。 這對尖括號通常叫做 diamond. 舉個例子, 考慮下面的變數宣告: Map<String, List<String&

java核心技術卷 程式設計

為什麼要使用泛型程式設計          泛型程式設計(Generic programming)意味著編寫的程式碼可以被很多不同型別的物件所重用。例如,我們並不希望為聚集String和File物