Конвертировать Java Legacy Code в Generic - Как заменить объект с типом?

StackOverflow https://stackoverflow.com/questions/2783613

Вопрос

// Наследный код

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), но мне было интересно узнать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top