Java泛型方法引用:類型擦除如何影響方法調用并如何解決?

Java泛型與方法引用:類型擦除的挑戰與解決方案

本文深入探討Java泛型在方法引用中的行為,特別是類型擦除如何影響方法調用,并提供有效的解決方案。

Java泛型方法引用:類型擦除如何影響方法調用并如何解決?

問題背景:

文中以mybatis-Plus為例,說明了redCar和YellowCar繼承自Car類,并分別擁有getStatus方法。泛型類BaseCarController的子類RedCarController和YellowCarController分別使用RedCar和YellowCar作為泛型類型參數。BaseCarController中的test方法試圖使用方法引用t::getStatus調用子類的getStatus方法,但實際運行時卻調用了Car類的getStatus方法,導致數據更新失敗。此外,文章還探討了如何動態獲取RedCar對象實例的getStatus方法引用。

立即學習Java免費學習筆記(深入)”;

問題分析:

問題的核心在于Java泛型的類型擦除機制。編譯時,泛型類型信息會被擦除,t::getStatus在編譯后實際變為Car::getStatus。這是因為Java泛型只在編譯期存在,運行期類型信息丟失,虛擬機看到的只有原始類型Car。因此,BaseCarController中的t::getStatus無法根據運行時的實際類型(RedCar或YellowCar)進行動態綁定。

解決方案:

為了解決第一個問題(在BaseCarController中正確調用子類的getStatus方法),應使用實例方法引用代替靜態方法引用。修改后的BaseCarController的test方法需要接收一個t類型的實例作為參數:

public class BaseCarController<T extends Car> {     @Autowired     CommonService cs;      public void test(T car, int id) {         cs.toggle(id, car::getStatus); // 使用實例方法引用     } }

這樣,調用test方法時需傳入對應的RedCar或YellowCar實例,car::getStatus將正確引用實例對應的getStatus方法。

第二個問題(動態獲取RedCar對象的getStatus方法引用)的解決方法與第一個問題相同,直接使用實例方法引用:

RedCar redCar = new RedCar(); cs.toggle(id, redCar::getStatus); // 直接使用 redCar 對象的方法引用

這同樣利用實例方法引用避免了類型擦除問題,確保根據實際對象類型調用對應的getStatus方法。 CommonService.toggle方法需要能夠接受一個Supplier類型的參數,以接收getStatus方法的返回值。

通過使用實例方法引用,我們有效地規避了類型擦除的限制,實現了根據運行時實際對象類型調用相應getStatus方法的目標。

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享