
Java泛型与方法引用:巧妙避免子类方法被父类方法覆盖
本文分析Java泛型中使用方法引用时,特别是涉及继承关系时可能遇到的一个常见问题:父类泛型方法引用子类方法,编译后却调用了父类方法。 我们将探讨这个问题的根源以及有效的解决方法。
假设我们有三个类:Car、RedCar和YellowCar,其中RedCar和YellowCar继承自Car:
@Datapublic class Car { private String id; private int status;}@Datapublic class RedCar extends Car {}@Datapublic class YellowCar extends Car {}
在BaseCarController中,我们希望通过泛型T调用不同子类的getStatus方法:
立即学习“Java免费学习笔记(深入)”;
public class BaseCarController { @Autowired CommonService cs; public void test(int id) { // 这里的问题:编译器会选择Car的getStatus方法 cs.toggle(id, T::getStatus); }}public class RedCarController extends BaseCarController {}public class YellowCarController extends BaseCarController {}
预期中,RedCarController调用test方法时,应该执行cs.toggle(id, RedCar::getStatus);YellowCarController调用test方法时,应该执行cs.toggle(id, YellowCar::getStatus)。然而,由于Java泛型的类型擦除机制,编译器在编译BaseCarController时,T::getStatus会被替换成Car::getStatus,导致实际执行结果与预期不符,进而影响数据库更新(例如使用MyBatis-Plus)。
解决方法:使用实例方法引用
为了避免类型擦除带来的问题,我们可以使用实例方法引用代替静态方法引用。 需要将方法的参数修改为具体的Car对象实例,然后使用实例方法引用。
public class Car { public String getStatus() { return "Car::status"; }}class RedCar extends Car { @Override public String getStatus() { return "RedCar::status"; }}public class Controller { public void test(T car) { invoke(car::getStatus); // 实例方法引用 } private void invoke(Supplier supplier) { System.out.println(supplier.get()); }}
现在,通过传入具体的Car对象实例,例如RedCar redCar = new RedCar(); new Controller().test(redCar);,就能正确调用RedCar的getStatus方法。 CommonService.toggle方法也需要相应修改,接受一个Supplier作为参数,而不是直接使用类方法引用。 这种方法有效地规避了泛型类型擦除导致的问题,确保了预期行为的实现。
以上就是Java泛型方法引用中,如何避免子类方法被错误地替换为父类方法?的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/176314.html
微信扫一扫
支付宝扫一扫