Java開發筆記(六十)匿名內部類的優點

前面依次介紹了簡單接口和擴展接口,給出的範例都是自定義的接口代碼,其實Java系統自己就自帶了若干行爲接口,爲了更好地理解系統接口的詳細用法,接下來仍是從一個基礎的例子出發,抽絲剝繭地逐步說明接口的幾種調用方式。
早在闡述如何使用數組的時候,就提到Java提供了Arrays工具可用於數組變量的常見處理,例如該工具的copyOf方法用來複制數組、sort方法用來給數組排序等等。當時特別指出,對數組運用sort方法的排序結果是升序排列,那麼若想對數組進行降序操做的話,只有一個輸入參數的sort方法便無能爲力了。好在Arrays工具重載了其它幾種sort方法,有個sort方法容許在第二個參數中傳入比較器對象,則編譯器會自動把排序規則替換爲指定的比較器。這個數組元素的比較器就是系統自帶的接口,名稱叫作Comparator,該接口只定義了一個抽象方法compare,該方法的兩個數組參數分別是待比較的兩個數組元素,返回-1表示前一個元素要排在後一個元素的前面,返回1表示前一個元素要排在後一個元素的後面。故而只要本身寫個新的比較器,並調整compare方法的返回數值,便可命令編譯器按照指定規則排序。
爲了理清排序方法及其比較器的因緣脈絡,下面將從最基本、只有一個輸入參數的sort方法講起。首先對一個整型數組初始化賦值,再調用Arrays工具的sort方法對該數組進行排序,相應的操做代碼以下所示:html

	// 演示數組工具的默認升序排列
	private static void sortIntArrayAsc() {
		Integer[] intArray = { 89, 3, 67, 12, 45 };
		Arrays.sort(intArray); // Arrays的sort方法默認爲升序
		String ascDesc = "intArray的升序結果爲:";
		for (Integer item : intArray) {
			ascDesc = ascDesc + item + ", ";
		}
		System.out.println(ascDesc);
	}

 

運行如上的測試代碼,獲得如下的日誌信息:java

整型數組的升序結果爲:3, 12, 45, 67, 89, 

 

可見sort方法果真是默認按照升序排列。
接着嘗試本身定義一個數組比較器,主要是實現Comparator接口裏面的compare方法,調整一下輸入參數對應的返回值,使之按照降序方式排列。新定義的比較器代碼示例以下:程序員

//定義一個整型數組的降序比較器
public class SortDescend implements Comparator<Integer> {

	@Override
	public int compare(Integer o1, Integer o2) {
		//return Integer.compare(o1, o2); // 默認的參數順序是升序
		return Integer.compare(o2, o1); // 倒過來的參數順序變成了降序
	}
}

而後往比較方法sort中塞入第二個參數,取值爲剛定義的比較器實例「new SortDescend()」,修改以後的數組排序代碼見下:數組

	// 利用新定義的降序比較器實現對數組的降序排列
	private static void sortIntArrayDesc() {
		Integer[] intArray = { 89, 3, 67, 12, 45 };
		// sort方法支持按照指定的排序器進行排列判斷
		// 新定義的SortDescend類實現了降序排列
		Arrays.sort(intArray, new SortDescend());
		String descDesc = "intArray的降序結果爲:";
		for (Integer item : intArray) {
			descDesc = descDesc + item + ", ";
		}
		System.out.println(descDesc);
	}

 

再次運行數組排序的測試代碼,此時輸出瞭如下的日誌信息:ide

整型數組的降序結果爲:89, 67, 45, 12, 3, 

 

從日誌結果發現,利用比較器SortDescend果然實現了整型數組的降序處理。
經過書寫全新的數組比較器,當然可以實現指定的排序操做,但是也有幾個不便之處:
第一,簡簡單單的幾行compare代碼,就得專門開個代碼文件保存,着實耗費不小。
第二,即便不另外開闢代碼文件,僅僅在原代碼中增長一個內部類,也會把排序方法與比較器隔開一段距離,儘管說距離產生美,但距離也會產生隔閡呀。
第三,要是比較器的判斷邏輯依賴於sort方法以前的某個局部變量,難不成比較器還得弄個構造方法傳入這個局部變量的數值?
上述的幾個問題雖然總有辦法解決,不過如有便捷的方案顯然更受歡迎。爲此Java創造了一種名叫「匿名內部類」的概念,這個「匿名內部類」本質上屬於內部類,但它表面看來沒有名字,於是被稱做「匿名」。其實就算開發者沒給它命名,編譯器也要自動給它取個代號,好比路人甲、路人乙、類A、類B等等,之因此省略了內部類的名稱,是由於該方式爲一種簡化的寫法。只要程序員給足了必要的信息,內部類的形態不完整沒有關係,編譯器會根據上下文自行推斷此處的代碼邏輯。而且匿名內部類的方法定義與實例建立操做合二爲一,代碼寫起來更加流利,看到這裏是否是躍躍欲試了呢?下面立刻給出「匿名內部類」的實例建立格式:工具

		new 接口名稱() {
			// 這裏要實現該接口聲明的抽象方法
		}

 

觀察上面的匿名代碼格式,能夠看到兩個重要信息,一個是new表示建立實例對象,另外一個是接口名稱表示該對象實現了指定接口,剩下起名字這種例行公事就交給編譯器代勞了。既然見過了匿名內部類的使用格式,接着就把它應用到數組排序器當中,對於sort方法而言,至關於原來「new SortDescend()」的位置換成了匿名內部類的實例建立代碼,替換以後的排序代碼以下所示:測試

	// 經過匿名內部類完成自定義的排序操做
	private static void sortIntArrayDescAnonymous() {
		Integer[] intArray = { 89, 3, 67, 12, 45 };
		// 匿名內部類無需專門定義形態完整的類,只需指明新建立的實例從哪一個接口擴展而來
		Arrays.sort(intArray, new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return Integer.compare(o2, o1); // 倒過來的參數順序變成了降序
			}
		});
		String descDesc = "intArray採起匿名內部類的降序結果爲:";
		for (Integer item : intArray) {
			descDesc = descDesc + item + ", ";
		}
		System.out.println(descDesc);
	}

 

可見有了匿名內部類,今後無需額外定義專門的內部類,乃至單獨的代碼文件了。
數組比較器不只適用於整型數組,還能用於其它類型好比字符串數組。當Arrays工具的sort方法給字符串數組排序的時候,默認是根據首字母的拼寫順序來升序排列,可是字符串時常須要按照長度排序,如此一來得從新實現一個按照字符串長度進行排序的比較器。如今利用匿名內部類,比較兩個字符串長度的代碼也能緊跟着sort方法了,具體的字符串排序代碼以下所示:日誌

	// 經過匿名內部類對字符串數組按照字符串長度進行排序
	private static void sortStrArrayByLength() {
		String[] strArray = { "說曹操曹操就到", "東道主", "風馬牛不相及", "亡羊補牢", "無巧不成書",
				"冰凍三尺非一日之寒", "同學", "青出於藍而勝於藍" };
		// 字符串數組的默認排序方式爲根據首字母的拼寫順序,
		// 下面的匿名內部類把排序方式改爲了按照字符串長度進行排序
		Arrays.sort(strArray, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				// 比較先後兩個數組元素的字符串長度大小
				return o1.length() < o2.length() ? -1 : 1;
			}
		});
		String desc = "strArray比較字符串長度的升序結果爲:";
		for (String item : strArray) {
			desc = desc + item + ", ";
		}
		System.out.println(desc);
	}

 

運行以上的排序代碼,觀察獲得的日誌的確輸出了排序好的字符串數組:htm

字符串數組比較字符串長度的升序結果爲:同學, 東道主, 亡羊補牢, 無巧不成書, 風馬牛不相及, 說曹操曹操就到, 青出於藍而勝於藍, 冰凍三尺非一日之寒, 

  

更多Java技術文章參見《Java開發筆記(序)章節目錄對象

相關文章
相關標籤/搜索