Java泛型方法引用中,如何避免子類方法被錯誤地替換為父類方法?

Java泛型方法引用中,如何避免子類方法被錯誤地替換為父類方法?

Java泛型與方法引用:巧妙避免子類方法被父類方法覆蓋

本文分析Java泛型中使用方法引用時,特別是涉及繼承關(guān)系時可能遇到的一個常見問題:父類泛型方法引用子類方法,編譯后卻調(diào)用了父類方法。 我們將探討這個問題的根源以及有效的解決方法

假設(shè)我們有三個類:Car、redCar和YellowCar,其中RedCar和YellowCar繼承自Car:

@Data public class Car {     private String id;     private int status; }  @Data public class RedCar extends Car { }  @Data public class YellowCar extends Car { }

在BaseCarController中,我們希望通過泛型T調(diào)用不同子類的getStatus方法:

立即學(xué)習(xí)Java免費(fèi)學(xué)習(xí)筆記(深入)”;

public class BaseCarController<T extends Car> {     @Autowired     CommonService cs;      public void test(int id) {         // 這里的問題:編譯器會選擇Car的getStatus方法         cs.toggle(id, T::getStatus);      } }  public class RedCarController extends BaseCarController<RedCar> {} public class YellowCarController extends BaseCarController<YellowCar> {}

預(yù)期中,RedCarController調(diào)用test方法時,應(yīng)該執(zhí)行cs.toggle(id, RedCar::getStatus);YellowCarController調(diào)用test方法時,應(yīng)該執(zhí)行cs.toggle(id, YellowCar::getStatus)。然而,由于Java泛型的類型擦除機(jī)制,編譯器在編譯BaseCarController時,T::getStatus會被替換成Car::getStatus,導(dǎo)致實(shí)際執(zhí)行結(jié)果與預(yù)期不符,進(jìn)而影響數(shù)據(jù)庫更新(例如使用mybatis-Plus)。

解決方法:使用實(shí)例方法引用

為了避免類型擦除帶來的問題,我們可以使用實(shí)例方法引用代替靜態(tài)方法引用。 需要將方法的參數(shù)修改為具體的Car對象實(shí)例,然后使用實(shí)例方法引用。

public class Car {     public String getStatus() { return "Car::status"; } }  class RedCar extends Car {     @Override     public String getStatus() { return "RedCar::status"; } }  public class Controller<T extends Car> {     public void test(T car) {         invoke(car::getStatus); // 實(shí)例方法引用     }      private void invoke(Supplier<String> supplier) {         System.out.println(supplier.get());     } }

現(xiàn)在,通過傳入具體的Car對象實(shí)例,例如RedCar redCar = new RedCar(); new Controller().test(redCar);,就能正確調(diào)用RedCar的getStatus方法。 CommonService.toggle方法也需要相應(yīng)修改,接受一個Supplier作為參數(shù),而不是直接使用類方法引用。 這種方法有效地規(guī)避了泛型類型擦除導(dǎo)致的問題,確保了預(yù)期行為的實(shí)現(xiàn)。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊8 分享