java泛型与方法引用:类型擦除的挑战与解决方案
本文深入探讨Java泛型在方法引用中的行为,特别是类型擦除如何影响方法调用,并提供有效的解决方案。
问题背景:
文中以MyBatis-Plus为例,说明了RedCar和YellowCar继承自Car类,并分别拥有getStatus方法。泛型类BaseCarController的子类RedCarController和YellowCarController分别使用RedCar和YellowCar作为泛型类型参数。BaseCarController中的test方法试图使用方法引用t::getStatus调用子类的getStatus方法,但实际运行时却调用了Car类的getStatus方法,导致数据更新失败。此外,文章还探讨了如何动态获取RedCar对象实例的getStatus方法引用。
问题分析:
问题的核心在于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方法的目标。
以上就是Java泛型方法引用:类型擦除如何影响方法调用并如何解决?的详细内容,更多请关注知识资源分享宝库其它相关文章!
版权声明
本站内容来源于互联网搬运,
仅限用于小范围内传播学习,请在下载后24小时内删除,
如果有侵权内容、不妥之处,请第一时间联系我们删除。敬请谅解!
E-mail:dpw1001@163.com
发表评论