1. 程式人生 > 其它 >列舉和泛型

列舉和泛型

列舉和泛型

本章目標

  • 掌握列舉型別及使用
  • 掌握泛型的特性
  • 重點掌握泛型的使用

列舉的定義

列舉是一個被命名的整型常數的集合,用於宣告一組帶識別符號的常數

  • 列舉在曰常生活中很常見,例如一個人的性別只能是“男”或者“女”,一週的星期只能是 7 天中的一個等。類似這種當一個變數有幾種固定可能的取值時,就可以將它定義為列舉型別。
  • •在 JDK 1.5 之前沒有列舉型別,那時候一般用介面常量來替代。列舉型別是 JDK1.5 引入的新型別,在 Java 中它雖然算個“小”功能,卻給我們開發帶來了“大”方便

宣告列舉

宣告列舉時必須使用 enum 關鍵字,然後定義列舉的名稱、可訪問性、基礎型別和成員等

列舉宣告的語法如下:

enum-modifiers enum enumName {   
 	enum-body,
}
  • enum-modifiers 表示列舉的修飾符主要包括 public、private 和 internal
  • enumname 表示宣告的列舉名稱
  • enum-body 表示列舉的成員,它是列舉型別的命名常數

舉例

//定義一個表示性別的列舉型別 SexEnum
public enum SexEnum {
	MALE,FEMALE;
}

//定義一個表示顏色的列舉型別 ColorEnum
public enum ColorEnum {
	RED,BLUE,GREEN,BLACK;
}

//使用列舉
ColorEnum color = ColorEnum.RED; 
switch ( color )  {            
      case RED: 
           color = ColorEnum.GREEN;                      
           break;            
      case YELLOW:                
           color = ColorEnum.RED;                              
           break;           
      case GREEN:                
           color = ColorEnum.YELLOW;                    
           break;      
 }   

列舉類

Java 中的每一個列舉都繼承自 java.lang.Enum 類。當定義一個列舉型別時,每一個列舉型別成員都可以看作是 Enum 類的例項,這些列舉成員預設都被 final、public, static 修飾,當使用列舉型別成員時,直接使用列舉名稱呼叫成員即可。

所有列舉例項都可以呼叫 Enum 類的方法,常用方法如下:

  • values():以陣列形式返回列舉型別的所有成員
  • valueOf():將普通字串轉換為列舉例項
  • compareTo():比較兩個列舉成員在定義時的順序
  • ordinal():獲取列舉成員的索引位置
EnumMap類

EnumMap 是專門為列舉型別量身定做的 Map 實現。雖然使用其他的 Map(如

HashMap)實現也能完成列舉型別例項到值的對映,但是使用 EnumMap 會更加高效。

// 定義型別列舉
public enum DataBaseType {    
      MYSQUORACLE,DB2,SQLSERVER
}

// 建立 EnumMap例項
EnumMap<DataBaseType,String>urls = new EnumMap<DataBaseType,String>(DataBaseType.class);
urls.put(DataBaseType.DB2,"jdbc:db2://localhost:5000/sample"); urls.put(DataBaseType.MYSQL,"jdbc:mysql://localhost/mydb");   urls.put(DataBaseType.ORACLE,"jdbc:oracle:thin:@localhost:1521:sample");   urls.put(DataBaseType.SQLSERVER,"jdbc:microsoft:sqlserver://sql:1433;Database=mydb");
EnumSet 類

EnumSet 是列舉型別的高效能 Set 實現,它要求放入它的列舉常量必須屬於同一列舉型別。EnumSet 提供了許多工廠方法以便於初始化

泛型

什麼是泛型

泛型,即“引數化型別”。一提到引數,最熟悉的就是定義方法時有形參,然後呼叫此方法時傳遞實參。那麼引數化型別怎麼理解呢?顧名思義,就是將型別由原來的具體的型別引數化,類似於方法中的變數引數,此時型別也定義成引數形式(可以稱之為型別形參),然後在使用/呼叫時傳入具體的型別(型別實參)。

  • 泛型的本質是為了引數化型別(在不建立新的型別的情況下,通過泛型指定的不同型別來控制形參具體限制的型別)
  • 在泛型使用過程中,操作的資料型別被指定為一個引數,這種引數型別可以用在類、介面和方法中,分別被稱為泛型類、泛型介面、泛型方法
泛型的作用
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);

for (int i = 0; i < arrayList.size(); i++) {
    String value = (String)arrayList.get(i);
    System.out.println(“item = " + item);
}

程式的執行結果會以崩潰結束

  • ArrayList 可以存放任意型別,例子中添加了一個 String 型別,添加了一個Integer 型別,再使用時都以 String的方式使用,因此程式崩潰了
  • 為了在編譯階段解決類似這樣的問題,泛型應運而生
泛型的特性

泛型只在編譯階段有效

List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();

Class classStringArrayList   = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if (classStringArrayList.equals(classIntegerArrayList)){
    System.out.println("型別相同");
}

泛型型別在邏輯上看以看成是多個不同的型別,實際上都是相同的基本型別

  • 編譯之後程式會採取去泛型化的措施。也就是說 Java 中的泛型,只在編譯階段有效
  • 在編譯過程中,正確檢驗泛型結果後,會將泛型的相關資訊擦出,並且在物件進入和離開方法的邊界處新增型別檢查和型別轉換的方法。也就是說,泛型資訊不會進入到執行時階段
泛型的使用
泛型類

泛型型別用於類的定義中,被稱為泛型類,通過泛型可以完成對一組類的操作對外開放相同的介面(最典型的就是各種容器類,如:List、Set、Map)

public class className <T> {
    private T variable;
    ...
  }
}
泛型介面

泛型介面與泛型類的定義及使用基本相同,泛型介面常被用在各種類的生產器中

//定義一個泛型介面
public interface Generator<T> {
    public T next();
}

//實現泛型介面
public class FruitGenerator implements Generator<String> {
    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}
泛型萬用字元 ?

同一種泛型可以對應多個版本(因為引數型別是不確定的),不同版本的泛型類例項是不相容的

//型別萬用字元一般是使用?代替具體的型別實參
public void showKeyValue1(Genreic<?> obj) {
    System.out.println("key value is " + obj.getKey());
}
  • 可以解決當具體型別不確定的時候,可以使用萬用字元 ?
  • 當操作型別時,不需要使用型別的具體功能時,只使用 Object 類中的功能,那麼可以用 ? 萬用字元來表未知型別
泛型方法的定義

泛型類是在例項化類的時候指明泛型的具體型別,而泛型方法是在呼叫方法的時候指明泛型的具體型別

//定義泛型方法
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}
  • public 與 返回值中間非常重要,可以理解為宣告此方法為泛型方法
  • 只有聲明瞭 的方法才是泛型方法,泛型類中的使用了泛型的成員方法並不是泛型方法
  • 表明該方法將使用泛型型別T,此時才可以在方法中使用泛型型別T
  • 與泛型類的定義一樣,此處T可以隨便寫為任意標識,常見的如T、E、K、V等形式的引數常用於表示泛型
泛型方法的應用
  • 泛型方法與可變引數
public <T> void printMsg( T... args){
    for(T t : args){
       System.out.println("t is " + t);
    }
}

可變引數的泛型方法與普通泛型方法本質上沒有任何區別

  • 靜態方法與泛型
public class StaticGenerator<T> {
    public static <T> void show(T t){
	…
    }
}

如果在類中定義使用泛型的靜態方法,需要新增額外的泛型宣告,即使靜態方法要使用泛型類中已經宣告過的泛型也不可以

總結

泛型在 Java 中有很重要的地位,在面向物件程式設計及各種設計模式中有非常廣泛的應用

在實際的程式設計過程中,自己可以使用泛型去簡化開發且能很好的保證程式碼質量