Я работаю над (простым) своего рода решением для кэширования, где служба может запрашивать объект Cache с карты кэшей. Объект Cache по сути работает так же, как и карта, с ключом, значением и методами для доступа и хранения объектов.
Я придумал следующее решение, но, как вы можете видеть, оно содержит приведение (потому что get () не может знать, какими должны быть типы вложенного объекта).
private final Map<String, Cache<?, ?>> caches = new HashMap<String, Cache<?, ?>>();
public <K, V> Cache<K, V> getOrCreateCache(String identifier) {
if (caches.containsKey(identifier)) {
return (Cache<K, V>) caches.get(identifier);
} else {
Cache<K, V> cache = new CacheImpl<K, V>();
caches.put(identifier, cache);
return cache;
}
}
private void test() {
Cache<String, String> strCache = getOrCreateCache("string cache");
strCache.set("key", "value");
}
Теперь мои вопросы:
- Является ли это «безопасным» подходом при условии правильной обработки исключений класса? (вероятно, поймать их и упаковать в специальный класс исключений)
- Есть ли «безопасная» альтернатива? Один с дженериками, если это вообще возможно, потому что я люблю их и не люблю касты.
- (не имеет прямого отношения) Является ли этот потокобезопасным? Я предполагаю, что нет, но тогда я не специалист по потокам. Достаточно ли просто синхронизировать весь метод или это (с полдюжины клиентов) вызовет слишком много накладных расходов / блокировок? Есть ли для этого подходящее решение?
Edit: Woo, много ответов, спасибо! Редактирование здесь, чтобы описать странность, которую я обнаружил во время тестирования:
Cache<String, String> someCache = service.getOrCreateCache(cacheIdentifier);
someCache.set("asdf", "sdfa");
Cache<String, Integer> someCacheRetrievedAgain = service.getOrCreateCache(cacheIdentifier);
System.out.println(someCacheRetrievedAgain.get("asdf")); // prints "sdfa". No errors whatsoever. Odd.