Я работаю над (простым) кешированием, которое может запрашивать объект Cache из карты кешей. Объект Cache работает практически так же, как и Map, с ключом и значением и методами доступа и хранения объектов.Java generics - Карта (типизированных) карт
Я придумал следующее решение, но, как вы можете видеть, он содержит приведение (потому что 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");
}
Теперь мои вопросы:
- Является ли это 'безопасный' подход, до тех пор, как classcastexceptions обрабатываются должным образом? (вероятно, поймать их и упаковать в специальный класс исключений)
- Есть ли «безопасная» альтернатива? Один с дженериками, если это вообще возможно, потому что мне они нравятся и не любят броски.
- (не связано напрямую) Является ли это потокобезопасным? Я предполагаю, что нет, но тогда я не специалист по нарезке. Достаточно ли просто сделать весь метод синхронизированным, или это (с полдюжины клиентов) вызовет слишком много накладных расходов/блокировок? Для этого есть опрятное решение?
Редактировать: 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.
Мне нравится расширение ArrayList, чтобы быстро составить идентификатор сортов, хороший трюк, должен запомнить его. Я попробую ваше решение. – fwielstra
После попытки: мне очень нравится ваше решение. При попытке получить объект кэша с другим типом возвращается новый объект кеша. Элегантный. Объект идентификатора кеша также может быть постоянно сохранен в клиентах, так как неизменяемая косая черта не изменяется. – fwielstra
Рассмотрите возможность использования com.google.common.collect.MapMaker.makeComputingMap для поточно-безопасного решения. Замените ArrayList собственным классом, если вы хотите сохранить память и/или время (не забудьте реализовать hashCode и равно). – maaartinus