如何在界面中使用guava类实例映射?

时间:2017-11-01 09:18:53

标签: java interface static guava

我有一个名为RestClientInterface的接口,它由抽象的RestClient类实现,这些类由SearchRestClient和IndexRestClient扩展。这两个类都是单身人士。我希望能够在接口静态方法getInstance中实现。我决定使用像这里建议的Guava库:How can I implement abstract static methods in Java?

我在界面中实现了两个静态方法:

public interface RestClientInterface {

    ClassToInstanceMap<RestClientInterface> classToInstanceMap = MutableClassToInstanceMap.create();

    static <T extends RestClientInterface> T getInstance(Class<T> type) {
        return classToInstanceMap.getInstance(type);
    }

    static <T extends RestClientInterface> void registerInstance(Class<T> type, T identity) {
        classToInstanceMap.putIfAbsent(type, identity);
    }
}

两个扩展类中的下一个已注册实例:

public class IndexRestClient extends RestClient {

    static {
        RestClientInterface.registerInstance(IndexRestClient.class, getInstance());
    }

    /**
     * IndexRestClient singleton.
     */
    private static IndexRestClient instance = null;

    private IndexRestClient() {}

    /**
     * Return singleton variable of type IndexRestClient.
     *
     * @return unique instance of IndexRestClient
     */
    private static IndexRestClient getInstance() {
        if (Objects.equals(instance, null)) {
            synchronized (IndexRestClient.class) {
                if (Objects.equals(instance, null)) {
                    instance = new IndexRestClient();
                    instance.initiateClient();
                }
            }
        }
        return instance;
   } 
}

接下来我称之为:

IndexRestClient restClient = RestClientInterface.getInstance(IndexRestClient.class);

但每次我都会失效。由于已注册实例的数组为空,因此实例的静态注册不起作用。我怎样才能正确地实例化这两个类?

2 个答案:

答案 0 :(得分:2)

在我们讨论之后,问题可能与类IndexRestClient的延迟加载有关,如果它在进一步使用之前在语句RestClientInterface.getInstance(IndexRestClient.class)中单独引用,因为我不确定对{的引用{1}}足以触发类的加载/初始化。

假设这里的问题确实是关于延迟加载的类IndexRestClient.class,你需要反转注册逻辑的控制, ie 而不是IndexRestClient注册本身与注册表,中间有一个“IndexRestClient”,负责处理它。

然而,在我看来,Registrar的合同应该更改,因为它不能解释您的Rest客户端的具体类型,而我知道您想要隐藏其创建的实现。

您可能想看看Java service loader机制,这似乎与您想要做的很接近,例如:

RestClientInterface

Service Loader模式可能提供更多的封装并隐藏更多的实现(因为您显然使用的是具体类型),但我觉得值得一提。

答案 1 :(得分:-1)

那是因为classToInstanceMap对象不是静态的,而你使用的方法是静态的。这意味着只有在创建类的新实例时才会创建映射。只需将static关键字添加到此对象。