Конвертировать Java Legacy Code в Generic - Как заменить объект с типом?
-
03-10-2019 - |
Вопрос
// Наследный код
void setCacheValue(String name, Object value){
getServletContext().setAttribute(name, value);
}
Object getCacheValue(String name){
return getServletContext().getAttribute(name);
}
// Итак, я хочу использовать универсальный для «Безопасности типа»
// first, set method seems working perfectly
<T> void setCacheObject(String name, T value){
getServletContext().setAttribute(name, value);
}
// Тогда, вот идет беда
<T> T getCacheValue(String name){
// of course, I cannot change servlet class - it returns Object type
Object value = getServletContext().getAttribute(name);
// would this work:
return (T) value;
// this cast is meaningless... but how should I do it?
}
// Это то, что я чего добиться в моем чистый Вызов кода:
{
double x = 1.2;
setCacheValue("x", x);
//...
// later
Double value = getCacheValue("x");
// too bad cannot use primitive type - it cannot handle null
}
Итак, какой правильный способ сделать это?
Решение
Это действительно невозможно. Вам нужно будет пройти «бетон» T
Как-то как аргумент метода, так что фактический тип известен во время выполнения. Обычно используемый подход проходит его как Class<T>
, так что вы можете использовать Class#cast()
:
<T> T getCacheValue(String name, Class<T> type) {
return type.cast(getServletContext().getAttribute(name));
}
Вы можете использовать его следующим образом:
Double value = getCacheValue("x", Double.class);
Другие советы
Карта Generics поддерживает тип на всех значениях карты, а не другой тип для определенных значений. Вы можете увидеть, как подделать это здесь. Отказ В основном идея заключается в том, что вы должны иметь безопасность типа на ключ, где клавиша имеет универсальный тип на нем, который существует просто для ассоциирования со значением.
В конце дня вы не сможете сделать это без небезопасного отряда, но вы можете сделать это таким образом, что делает его чрезвычайно маловероятным, что есть проблема с актером и таким образом, что является типовым фактором Пользователи вашего класса.
На самом деле это тоже компилирует:
public class Test
{
<T> T getCacheValue(String name){
// of course, I cannot change servlet class - it returns Object type
Object value = getServletContext().getAttribute(name);
// would this work:
return (T) value;
// this cast is meaningless... but how should I do it?
}
public static void main(String... args)
{
Test t = new Test();
Double double = t.<Double>getCacheValue("Double");
}
}
Это бессмысленно (может быть, если вы добавите TypeCheck), но мне было интересно узнать.