重載是實現(xiàn)多態(tài)非常重要的手段之一提针,但是在使用重載時,往往也容易出現(xiàn)預(yù)料之外的結(jié)果海雪,因此在使用重載,尤其是方法的重載時要尤其的謹(jǐn)慎舱殿。
使用方法重載可能帶來的問題
- 方法的重載和繼承時的覆蓋不同
繼承時的覆蓋機制是:選擇被覆蓋的方法的正確版本是在運行時進行的奥裸,選擇的依據(jù)是被調(diào)用方法所在對象的運行時類型。
因此
class Wine {
String name() { return "wine"; }
}
class SparklingWine extends Wine {
@Override
String name() { return "sparkling wine"; }
}
class Champagne extends SparklingWine {
@Override
String name() { return "champagne"; }
}
public class Overriding {
public static void main(String[] args) {
List<Wine> wineList = List.of(new Wine(), new SparklingWine(), new Champagne());
for (Wine wine : wineList)
System.out.println(wine.name());
}
}
的輸出是:“wine沪袭,sparking wine 和 champagne”
二方法的重載機制則湾宙,要調(diào)用哪個方法是在編譯時做出決定的。如下面這段代碼
// Broken! - What does this program print?
public class CollectionClassifier {
public static String classify(Set<?> s) {
return "Set";
}
public static String classify(List<?> lst) {
return "List";
}
public static String classify(Collection<?> c) {
return "Unknown Collection";
}
public static void main(String[] args) {
Collection<?>[] collections = {
new HashSet<String>(),
new ArrayList<BigInteger>(),
new HashMap<String, String>().values()
};
for (Collection<?> c : collections)
System.out.println(classify(c));
}
}
最后只會輸出三次“Unknown Collection”冈绊。因為參數(shù)編譯時的類型都是Collection<?>.
Java5 引入自動裝箱之后侠鳄,重載尤其尤其需要謹(jǐn)慎
如List 的remove(Integer e) 和remove(int i) 就是兩個完全不同的方法。前者是移除列表中的指定對象死宣,后者是移除列表中指定位置的對象伟恶。lambda 和方法引用也可能引起方法重載的混亂
因為lambda 和方法引用時的函數(shù)式方法本身也可能被重載,其返回結(jié)果可能會超出我們的預(yù)料毅该,與重載搭配使用可能出現(xiàn)混亂博秫。如下面這段代碼:
new Thread(System.out::println).start();
ExecutorService exec = Executors.newCachedThreadPool();
exec.submit(System.out::println);
submit 方式其實帶有一個Callable<T>的重載,盡管我們認(rèn)為println 方法沒有返回值眶掌,可是萬一println也被重載了挡育,那么結(jié)果就會超出我們的預(yù)料了。
解決方法
由此可見朴爬,使用方法重載很可能會出現(xiàn)預(yù)料之外的結(jié)果静盅,因此,非必要情況下盡量不要使用方法的重載寝殴≥锏可以避開的方式有:
- 對于相同名稱的方法,使用不同數(shù)量的入?yún)?/li>
- 入?yún)⑾嗤瑫r蚣常,更改方法名稱
- 是在無法更改方法名稱的場景(構(gòu)造器)市咽,如果遇到入?yún)?shù)量相同時,考慮使用靜態(tài)工廠模式初始化類
思考
非必要不重載抵蚊。因為重載會降低代碼的可讀性施绎,讓程序員無法在編寫和閱讀代碼時就能快速準(zhǔn)確的判斷出到底調(diào)用的是哪個方法。由此可能產(chǎn)生錯誤贞绳。