到底 <T extends Comparable<? super T>>是什麼意思
December 23, 2018每次看到聲明中有
<T extends Comparable<? super T>>
都會想辦法研究一下 搞懂之後 過幾天又忘記了 為了減少下次複習的時間 也為了分享學習的心得 產生了這篇文章 而且我也很有信心這篇會是網路上講解這個聲明最清楚的文章
希望讀者可以先看過Item31之後 再來讀這篇
前情提要
以下的聲明 大家都看得懂
限制是說 T必須要實作Comparable<T>(只有這樣 T之間才能互相比大小) 比如具體類T是Student 那它必須 implements Comparable<Student>
限制是說 T必須要實作Comparable<T或是T的任意父類>(只有這樣 T的實例之間 或是T和他的父類的實例之間 才能互相比大小)
以上的定義取自Item31
但我相信各位看官根本有看沒有懂 這篇文章舉個實際例子 來讓你真正通透
Welcome to the jungle
先來各自定義一下兩種不同的sort
定義一下我們的類別 Person是父類 Student是子類 藉由年紀排序
建立一下我們的側資
好戲登場
對於這三組測資 猜猜哪些可以排序哪些不行
給你一分鐘 一分鐘後公佈答案
相信我 請認真的看一下mySort1跟mySort2的聲明 認真的想一下 這樣等一下看解釋的時候會學到最多 我不會害你
揭曉答案
答案是 第三個無法執行 且聽我娓娓道來
先看mySort1
如果輸入是List of T 那裡面的每個T都必須要有實作Comparable<T>
1.allPersons: T在這裡是Person 不用多說 Person有實作Comparable<Person> 當然可以跑
2.mixedPerson: T在這裡是Person 輸入參數中有些Person 有些Student 問題在於 Student有沒有實作Comparable<Person>呢 答案是有 因為繼承自Person
3.allStudent: T在這裡是Student Student有沒有實作Comparable<Student>呢 答案是沒有 Student只有實作Comparable<Person> 所以不能執行 compile-time爆錯
再看mySort2
如果輸入是List of T 那裡面的每個T都必須要有實作Comparable<T>
或是Comparable<T的父類>
1.allPersons: T在這裡是Person 不用多說 Person有實作Comparable<Person> 當然可以跑
2.mixedPerson: T在這裡是Person 輸入參數中有些Person 有些Student 問題在於 Student有沒有實作Comparable<Person>呢 答案是有 因為繼承自Person
3.allStudent: T在這裡是Student Student有沒有實作Comparable<Student>或是Comparable<Student的父類>呢 答案是有 Student有繼承Comparable<Person> 所以可以執行
老師我有問題
Q1.老師你偷懶 你的Student在繼承Person的同時 也同時實作Comparable<Student>不就好了嗎
A1.答案是不行 一個類別不能同時實作兩個不同類型的同個介面
你的Student不能同時實作Comparable<Student> 又同時有Comparable<Person>
Q2.不管啦 我就是要實作Comparable<Student>
A2.那你剩兩個選擇
第一個方法是Person也有實作Comparable<Person>然後Student不繼承Person 相信這不構成選項 Student沒繼承Person就是兩個完全不相關的類別 mixedPerson也無法創建
第二個選項 Person不實作Comparable<Person>
那這六個只剩3跟6可以 因為根本沒有人實作Comparable<Person>
結論
現在知道為什麼Comparable<? super T>
這麼重要了吧 因為一個類別不能同時實作兩個不同類型的同個介面
所以最好一個List中的所有人都繼承自最父類的Comparable
這麼一來Comparable<? super T>
這個宣告 就可以在類型安全的前提下 讓你的API最廣泛地被客戶使用
看看Oracle的官方文件Collection.sort 或是其他支援泛型的函式 都是這樣宣告的 相信看到這裡你已經知其然也知其所以然