程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Eclipse V3.1中的Java泛型支持

Eclipse V3.1中的Java泛型支持

編輯:關於JAVA

Java 中的泛型

幾乎從第一個版本開始,Java 技術的創立者們就已經開始討論對該語言添加 泛型支持。C++ 通過標准模板庫對泛型進行支持,但是由於缺少所有其他類(嵌 入在 Java 語言中的Object 類中)的一個統一父類,泛型的實現也受到阻礙。Java編程語言的泛型支持是其歷史上最重大的語法變化。由於某些顯而易見的原因,工具支持比其他 SDK 升級的步法要慢得多。盡管如此,現在 Eclipse V3.1 已經對這些語言的新特性有了出色的支持。本文重點介紹其中的一些新特 性。

Java 5 項目

為了打開 Eclipse V3.1 中的Java 泛型支持,需要在 機器上安裝 Java 5,從一些平常的地方都可以下載到 Java 5。泛型支持連同項 目屬性一起出現在編譯器設置頁面。這意味著像以前一樣,每個項目具有獨立的SDK 設置。為了創建使用泛型的項目,必須在創建項目時指定語言級別或者通過 現有項目的項目屬性指定語言級別。

Java 5 設置使用兩個特定的屬性頁 。第一個屬性頁指定編譯器設置。

圖 1. 針對 Java 5 支持的特定於編 譯器的設置

除非您已經在 Eclipse for Java 5 中設置了默認項目設置,否則需要為該 項目覆蓋那些設置。JDK compliance 區域允許您決定源文件和類文件的設置。當您把源文件設置為 5.0 級別時,就會獲得很多新的內容幫助和重構選項。

另一個相關屬性對話框是樹型視圖中的Errors/Warnings 區域。

圖 2. 項目屬性的Errors/Warnings 區域

大量 J2SE 5 選項能夠控制 Eclipse 為您的Java 5 代碼產生什麼類型的錯 誤和警告(請參見表 1)

J2SE 5 選項 警告類型 Unchecked generic type operation 編譯器每當遇到未經檢查的泛型類型操作, 就將發出一個錯誤或者警告。這種操作包括諸如 List 或 ArrayList 等類型上 的操作,但沒有指定類型。每當您使用一個保存有對象的舊式 Collection 類時 就會產生一個警告。 Generic type parameter declared with a final type bound 編譯器每當遇到一個涉及 final 類型的類 型綁定時,就會發出一個錯誤或者警告。請看這個示例方法簽名:

 

public int doIt(List<? extends String> list)

因為 String 是 final 類型,參數不能擴展 String,所以這樣寫比較有效:

public int doIt(List<String> list)

Inexact type match for vararg arguments 當編 譯器不能從 varargs 參數確定開發人員的意圖時,它將生成一個警告。有一些 與數組相關的varargs 是不明確的。 Boxing and unboxing conversions 對自動裝箱操作發出警告(裝箱操作可能影響性能),並 且不再對類型包裝對象做對象身份的假設。這是一個默認狀態下被忽略的小警告 。 Missing @Override annotation 應該為任何重 寫的方法包含 @Override 注釋。缺少這個注釋可能表示開發人員沒有意識到該 方法被重寫。 Missing @Deprecated annotation 由於缺少 @Deprecated 標志而產生的警告。 Annotation is used as super interface 您不能把 Deprecated 類作為超級接口。例 如,不推薦這種寫法:

 

public interface BadForm extends Deprecated {

}

Not all enum constants covered on switch switch 語句缺少枚舉項意味著您可能遺漏一些枚舉選項。 Unhandled warning tokens in @SuppressWarnings Java 5 允許您添加注釋以抑制編譯器警告。如果 您拼寫錯了一個警告或者使用了一個並不存在的警告,這個標志將發出一個警告 。 Enable @SuppressWarnings annotations 打開 程序地(用代碼)抑制您不關心的警告的能力。

一 旦您根據喜好設定了所有的項目選項,就可以開始在 Eclipse 中使用泛型了。

從特定類型向泛型轉換

請考慮清單 1 中的簡單類,它創建了一 個 Employee 和 Manager 對象的列表(Manager 擴展自 Employee),將他們打 印出來,給他們漲工資後再打印出來。

清單 1. HR 類

package  com.nealford.devworks.generics.generics;
import  java.util.ArrayList;
import java.util.Collections;
import  java.util.List;
public class HR {
  public HR() {
    List empList = new ArrayList(5);
     empList.add(new Employee("Homer", 200.0, 1995));
     empList.add(new Employee("Lenny", 300.0, 2000));
     empList.add(new Employee("Waylon", 700.0, 1965));
     empList.add(new Manager("Monty", 2000.0, 1933,
         (Employee) empList.get(2)));

    printEmployees (empList);

    System.out.println("----- Give  everyone a raise -----");
    for (int i = 0; i <  empList.size(); i++)
      ((Employee) empList.get (i)).applyRaise(5);

    printEmployees(empList);

    System.out.println("The maximum salary for any  employee is "+
        Employee.MAX_SALARY);

    System.out.println("Sort employees by salary");
     Collections.sort(empList);
    printEmployees (empList);

    System.out.println("Sort employees by  name");
    Collections.sort(empList, new  Employee.NameComparer());
    printEmployees(empList);

    System.out.println("Sort employees by hire  year");
    Collections.sort(empList,  Employee.getHireYearComparator());
    printEmployees (empList);
  }

  public void printEmployees(List  emps) {
    for (int i = 0; i < emps.size();  i++)
      System.out.println(emps.get(i));
  }

  public static void main(String[] args) {
     new HR();
  }
}

如果您打開了 Java 5 支持, 編譯這段代碼會出現多種警告信息。

快速修復特性

每當 Eclipse 要給您的代碼建議一種改進時,Eclipse 的快速修復特性就顯示為編輯器窗口左 側邊欄上的一個燈泡。在清單 1 中的代碼中,您將會看到多個快速修復。

圖 3. 快速修復燈泡指示您的代碼待改進

快速修復使用燈泡和黃色波浪線指示待改進處。如果將鼠標移動至黃色波浪 線上,可以看到出現在圖 4 中的改進建議。

圖 4. 快速修復指示什麼應該被通用化

這裡所列的快速修復建議只有一條建議。邊上的燈泡提出建議,添加一個本 地變量保存 List 的add() 方法的返回值。然而,在這裡該方法返回一個布爾 類型值,並且被忽略了。

為了定位快速修復建議,移至重構菜單。Eclipse 中很多重構與 Java 5 中的泛型直接相關。“Infer Generic Type Arguments”重構將給列表增加泛型支持。第一個對話框允許您選擇 選項。

圖 5. Infer Generic Type Arguments choices 對話框

第一個選項與一個結論相關,這個結論是 clone() 方法將返回接收者 類型而不是另外一個類型(相關類)。大部分功能良好的類都遵守這個規則,如 果您知道您的類不遵守這個規則,則不要選中這個選項。當第二個選項未選中時 ,將保留“raw”(非泛型)參數,而不是推斷出正確的泛型參數類 型。

Eclipse 中的大多數重構中,您都可以預覽您的類將發生什麼變化 。點擊這個對話框上的Preview 按鈕將出現圖 6 所示的對話框。

圖 6. Preview the generic refactoring

更新後的代碼如下:

清單 2. 更新後的代碼

List<Employee> empList = new  ArrayList<Employee>(5);
empList.add(new Employee("Homer",  200.0, 1995));
empList.add(new Employee("Lenny", 300.0,  2000));
empList.add(new Employee("Waylon", 700.0, 1965));
empList.add(new Manager("Monty", 2000.0, 1933,
     empList.get(2)));

代碼發生了兩個有趣的變化。第一 —— 也是最明顯的—— List 和 ArrayList 聲明現在 是 Employee 類型的泛型。第二 —— 不太明顯 —— 代 碼最後一行發生的變化。您觀察一下 Manager 類的原來的empList 添加,它的最後一個參數需要針對 Assistant 域強制類型轉換為 Employee。而 Infer 重 構足夠聰明,它可以刪除現在不必要的類型強制轉換。

在介紹完快速修 復之前,Eclipse 還在 Java 5 支持中增加了另外一個有趣的方面:您可以得到 為方法添加注釋的建議,比如 @Override。您還具有針對注釋的內容幫助。

圖 7. 針對注釋的快速修復和內容幫助擴展

快速幫助特性

Eclipse V3.1 已經添加了快速幫助以促進 Java 5 中的泛型支持。請考慮這個普通的for() 循環,參見清單 3 中的printEmployees() 方法。

清單 3. for() 循環

public void  printEmployees(List<Employee> emps) {
  for (int i  = 0; i < emps.size(); i++)
    System.out.println (emps.get(i));
}

除了對泛型的支持外,Java 5 現在也支 持 for...each 循環。快速幫助建議將 for loop 變成 for...each,變化後的代碼如清單 4 所示。

清單 4. for...each 循環

public void  printEmployees(List<Employee> emps) {
  for  (Employee emp : emps)
    System.out.println(emp);
}

這個版本由於完全刪除了 i 變量和 get() 方法調用而變得清潔 多了。

泛型類型

Eclipse V3.1 為了擴展到泛型類型而擴大了對 類型操作的支持。這意味著:

泛型類型能夠被安全地重命名。

類 型變量能夠被安全地重命名。

泛型方法能夠從泛型代碼中抽象出來或者 嵌入泛型代碼。

代碼幫助可以自動將合適的類型參數插入參數化的類型 中。

Eclipse 中的搜索工具對於泛型類型已經具有了更高的智能性。請 考慮如下代碼:

清單 5. 泛型類型

public void  doEmployeeAnalysis() {
  List<Employee> empList = new  ArrayList<Employee>(5);
  List<Date> hireDates  = new ArrayList<Date>(5);
  List<Integer>  departments = new ArrayList<Integer>(10);
  List<?  extends Employee> allMgrs = new ArrayList<Manager> (5);
  . . .

如果您選中第一個 List<Employee> 聲明並且選擇 Search > References > Project ,Eclipse 將顯示給您所有的list 聲明。

圖 8. Eclipse 在尋找泛型 引用方面已經變得聰明

您也可以通過 Search 窗口隱藏良好的特性來過濾這些結果。如果您訪問 Search 窗口菜單(在右上角,最小化和最大化按鈕的旁邊),您可以找到泛型 感知的過濾選項。

圖 9. 搜索窗口的過濾菜單允許您過濾泛型感知的結 果

如果您使用 Filter Incompatible 過濾結果,將刪除兩個不是基於 Employee 的條目。結果如圖 10 所示。

圖 10. Filter Incompatible 在搜索窗口過濾掉與非 Employee 相關的條目

深入了解泛型

不幸的是,Eclipse 不能解決您所有的泛型問題。事實 上,有時重構會為您要解決的問題產生語法正確但是語義不正確的代碼。具有諷刺意味的是,在泛型出現之前的那些日子更輕松,因為您必須將所有東西都作為 對象的泛型集合傳遞。而現在您必須小心地傳遞正確類型的集合。

考慮 這個例子。在 HR 應用程序中,您添加一個方法確定雇員的退休年齡。然而, Employee 的年齡是來自於 Employee 的父類:Person。寫一個方法只接受在這 個實例中工作的雇員,但是您不想將您的應用程序只用於雇員。如果將來您需要 查詢以前的雇員(作為 Persons),該怎麼辦呢?

這個問題的解決方案 在於靈活的泛型參數。請考慮清單 6 中的代碼,它接受任何擴展自 Person 的類。

清單 6. 示例 SELECT 語句

public List<Person>  empsOverRetirementAge(
            List<?  extends Person> people) {
  List<Person> retirees  = new ArrayList<Person>(1);
  for (Person e :  people)
    if (e.getAge() > 65)
       retirees.add(e);
  return retirees;
}

該方法 接受 Person 的任何子類,所以更靈活。使用泛型的時候,您應該牢記這一點。在本例中,泛型實際上比較特定(至少,他們應該稱這種語言特性為“特 定性”)。仔細識別參數類型能夠使您的代碼獲得同樣的靈活性,因此性 能比泛型更好,但是具有泛型提供的附加的類型安全性。

結束語

泛型支持大大增強了 Java 編程語言,工具供應商必然需要很長時間才能趕上。現在有了好的工具支持,您應該開始利用這種高級語言特性。它使代碼更加可讀 —— 因為刪除了類型強制轉換 —— 並且允許編譯器為 您做更多的工作。任何時候您都可以讓編譯器和其他的工具(如 IDE)做更多的工作,這意味著您要做的工作更少。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved