我有一个名为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);
但每次我都会失效。由于已注册实例的数组为空,因此实例的静态注册不起作用。我怎样才能正确地实例化这两个类?
答案 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关键字添加到此对象。