为了账号安全,请及时绑定邮箱和手机立即绑定

绕过java中静态方法的早期绑定

绕过java中静态方法的早期绑定

至尊宝的传说 2024-01-05 09:59:01
我有一个 AbstractBaseRepository。我所有的存储库都从这个类扩展。我创建了另一个类 RepositoryFactory 来创建 Repository 的任何实例。由于静态方法的早期绑定,我面临问题。public abstract class AbstractBaseRepository {    public static <T extends AbstractBaseRepository> T getNewInstance(EntityManagerFactory entityManagerFactory) {        throw new RuntimeException("Override and provide valid initialization");    }    ...}public class RepositoryFactory {    public static <T extends AbstractBaseRepository>  T getRepository(Class<T> cls) {               return T.getNewInstance(entityManagerFactory);    }    ...}一个示例子类public class DeviceModelRepo extends AbstractBaseRepository {    public static DeviceModelRepo getNewInstance(EntityManagerFactory entityManagerFactory) {        return new DeviceModelRepo(entityManagerFactory);    }    ...}每当我使用 AbstractBaseRepository 的有效子类调用 getRepository() 时,都会引发运行时异常。这是由于静态方法的早期绑定造成的。在编译时, getNewInstance 与 AbstractBaseRepository 绑定,而不是在运行时与类的实际类型绑定。有什么好的解决办法吗?
查看完整描述

2 回答

?
茅侃侃

TA贡献1842条经验 获得超21个赞

我的第一个建议是使用 Spring。获取使用某个接口创建的所有 bean 的列表非常容易。

另外,如果您将 Repository 实例视为一种“插件”,您可能会看到 Java 的 ServiceLoader 类如何提供帮助。

另外,另一种方法是在工厂中使用 switch 语句并为每种情况创建实例,而不是在 Repository 子类上使用静态方法。

最后,我不推荐反射解决方案,但有一些方法可以根据类的名称加载类并反射性地创建新实例。

但重写静态方法是不可能的。


查看完整回答
反对 回复 2024-01-05
?
撒科打诨

TA贡献1934条经验 获得超2个赞

通过查看您的代码,我了解到您希望拥有 AbstractBaseRepository 的不同实现,例如 DeviceModelRepo。然后你需要一个工厂类来创建AbstractBaseRepository的具体实现的实例。这里的主要问题是您尝试覆盖永远无法覆盖的静态方法,但子类将隐藏父实现。请不要使用静态方法进行覆盖。您可以按如下所示更改您的实施,此问题将得到解决。


public abstract class AbstractBaseRepository {

    public AbstractBaseRepository(EntityManagerFactory entityManagerFactory){

        ...

    }

    //removed method getNewInstance(EntityManagerFactory entityManagerFactory) 

    ...

}

然后是子类的下面的实现。


public class DeviceModelRepo extends AbstractBaseRepository {


    public DeviceModelRepo(EntityManagerFactory entityManagerFactory) {

        super(entityManagerFactory);

        ...

    }

    //removed method getNewInstance(EntityManagerFactory entityManagerFactory) 

    ...

}

现在我为您提供工厂类的两个实现。一是每个实现都有不同的方法,例如 getDeviceModelRepository()。另一种解决方案是使用反射并通过传递实现存储库类来获取存储库实例。


public class RepositoryFactory {

    //Solution-1, create separate method for each of repository like below

    public static AbstractBaseRepository getDeviceModelRepository() {       

        return new DeviceModelRepo(entityManagerFactory);

    }

    //Solution-2, use reflection to get instance of specific implementation

    //of AbstractBaseRepository

    public static <T extends AbstractBaseRepository> T 

        getRepository(Class<T> repoClass) throws Exception{


        return repoClass.getConstructor(EntityManagerFactory.class)

            .newInstance(entityManagerFactory);

    }

    ...

}

使用反射解决方案,您可以获得存储库实例,如下所示。


RepositoryFactory.getRepository(DeviceModelRepo.class)


查看完整回答
反对 回复 2024-01-05
  • 2 回答
  • 0 关注
  • 116 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信