当前位置: 首页 > 图灵资讯 > 技术篇> Java泛型方法引用中,如何避免子类方法被错误地替换为父类方法?

Java泛型方法引用中,如何避免子类方法被错误地替换为父类方法?

来源:图灵教育
时间:2025-02-27 17:18:24

java泛型方法引用中,如何避免子类方法被错误地替换为父类方法?

Java泛型和方法引用:巧妙地避免子类方法被父类方法覆盖:

本文分析了Java泛型中使用方法引用时可能遇到的一个常见问题,特别是在继承关系中:父类泛型引用子类方法,但在编译后调用父类方法。 我们将讨论这个问题的根源和有效的解决方案。

假设我们有三个类:Car、RedCar和YellowCar,其中,RedCar和YelowCar继承了Car:

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

@Data
public class RedCar extends Car {
}

@Data
public class YellowCar extends Car {
}

在Basecarcontrler中,我们希望通过泛型T调用不同子类的getstatus方法:

立即学习“Java免费学习笔记(深入);

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> {}

在预期中,Redcarcontrler调用test方法时,应执行cst方法.toggle(id, RedCar::getStatus);在调用test方法时,YellowCarController应执行cst.toggle(id, YellowCar::getStatus)。但由于Java泛型的类型擦除机制,编译器在编译BaseCarContrler时,T::getstatus将被Carrtatus取代::getStatus,实际执行结果与预期不一致,进而影响数据库更新(例如使用MyBatiss)-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<T extends Car> {
    public void test(T car) {
        invoke(car::getStatus); // 引用实例方法
    }

    private void invoke(Supplier<String> supplier) {
        System.out.println(supplier.get());
    }
}

现在,通过介绍特定的Car对象实例,如RedCar redCar = new RedCar(); new Controller().test(redCar);,RedCar的getStatus方法可以正确调用。 CommonService.togle方法也需要相应修改,接受Supplier作为参数,而不是直接引用类方法。 该方法有效避免了一般类型擦除引起的问题,保证了预期行为的实现。

以上是引用Java泛型方法时,如何避免将子类方法错误替换为父类方法?详情请关注图灵教育的其他相关文章!