java 泛型的方法引用相关问题?
各位大神早上好,请看我的问题:
@Datapublic class Car{
private String id;
private int status;
}
@Data
public class RedCar extends Car{
}
@Data
public class YellowCar extends Car{
}
RedCar、YellowCar 是 Car 的子类,正常情况下可以使用如下方法引用:queryWrapper.lambda().eq(RedCar::getId,1)
下面我创建了一个BaseCarController ,RedCarController、YellowCarController 都继承于它
public class BaseCarController<T extends Car> { @Autowired
CommonService cs;
public void test(int id) {
cs.toggle(id, T::getStatus);
}
}
public class RedCarController extends BaseCarController<RedCar> {
}
public class YellowCarController extends BaseCarController<YellowCar> {
}
原本以为:
调用 RedCarController 的 test 方法,应该执行的是cs.toggle(id, RedCar::getStatus);
调用 YellowCarController 的 test 方法,应该执行的是cs.toggle(id, YellowCar::getStatus);
但是发现 BaseCarController.class 文件中 T::getStatus 变成了Car::getStatus
导致 cs.toggle 方法中 mybatis-plus 没有成功更新对应的表。
请问这种情况怎么解决呢,怎么实现我上面的预期效果呢?
另外,如果我只有一个 redCar 对象RedCar redCar = new RedCar();
有没有什么方法,可以通过 redCar 这个对象达到 RedCar::getStatus 这个效果呢,类似如下:cs.toggle(id, 【通过redCar获取RedCar::getStatus】);
回答:
在我的认知中,实例方法是不能直接作为参数传递的。所以我很好奇 CommonService.toggle
是怎么定义的。假如我的认识无误,那说明 getStatus
是个静态方法。静态方法没有继承关系,在定义 BaseCarController 的时候,就已经决定了它是哪个类的静态方法。另外,从 Java 泛型具有类型擦除特性来说,T
的信息也是不会被保留使用的
测试代码:
public class Controller<T extends Car> { public void test() {
invoke(T::getStatus);
}
private void invoke(Supplier<String> supplier) {
System.out.println(supplier.get());
}
}
class RedController extends Controller<RedCar> { }
class YellowController extends Controller<YellowCar> { }
生成 .class 之后再反编译出来是这样的
public class Controller<T extends Car> { public Controller() {
}
public void test() {
this.invoke(Car::getStatus);
}
private void invoke(Supplier<String> supplier) {
System.out.println((String)supplier.get());
}
}
class RedController extends Controller<RedCar> {
RedController() { }
}
class YellowController extends Controller<YellowCar> {
YellowController() { }
}
可以看到,直接就是传入的 Car::getStatus
,在基类定义的时候并不知道会有哪些子类,而子类中也没有重载 test()
定义,所以只能找到 Car::getStatus
。
如果改成实例 Lambda(需要实例对象)应该可以达到你的要求。示例代码:
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); // 注意这里是实例 car 的方法,不是静态方法
}
private void invoke(Supplier<String> supplier) {
System.out.println(supplier.get());
}
}
public static void main(String[] args) { RedCar car = new RedCar();
new RedController().test(car);
}
回答:
根据题主的描述看,需求应该是根据实例对象redCar调用RedCar类的getStatus,那应该直接利用多态来实现比较好吧。测试代码如下:
public class Car { public void getStatus() {
System.out.println("Car getStatus");
}
}
public class RedCar extends Car {
public void getStatus() {
System.out.println("RedCar getStatus");
}
}
public class YellowCar extends Car{
public void getStatus() {
System.out.println("YellowCar getStatus");
}
}
public class BaseCarController { public void test(Car car) {
car.getStatus();
}
}
class RedCarController extends BaseCarController {
public static void main(String[] args) {
BaseCarController redCarController = new RedCarController();
redCarController.test(new RedCar()); // output: RedCar getStatus
}
}
class YellowCarController extends BaseCarController {
public static void main(String[] args) {
BaseCarController yellowCarController = new YellowCarController();
yellowCarController.test(new YellowCar()); // output: YellowCar getStatus
}
}
题主的代码中的“T::getStatus”认定了getStatus方法为静态方法,使用泛型会被擦除类型信息,直接编译为Car::getStatus。即使仍然使用静态方法定义getStatus,用Car的实例对象调用静态方法.getStatus(),也会在编译期直接转为Car.getStatus()。
所以我的理解是题主想要通过实例对象redCar调用的getStatus方法,只能是继承的实例方法,并用多态来实现调用对应各个类的getStatus方法。
以上是 java 泛型的方法引用相关问题? 的全部内容, 来源链接: utcz.com/p/944994.html