Domanda

// codice legacy

void setCacheValue(String name, Object value){
    getServletContext().setAttribute(name, value);
}
Object getCacheValue(String name){
    return getServletContext().getAttribute(name);
}

// quindi voglio usare generico per "la sicurezza di tipo"

// first, set method seems working perfectly
<T> void setCacheObject(String name, T value){
    getServletContext().setAttribute(name, value);
}

// allora, ecco che arriva il problema

<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?
}

// Questo è quello che quello che per raggiungere nel mio pulita chiamare il codice:

{
    double x = 1.2;
    setCacheValue("x", x);
    //...
    // later
    Double value = getCacheValue("x");
    // too bad cannot use primitive type - it cannot handle null

}

Quindi, qual è il modo corretto di fare questo?

È stato utile?

Soluzione

Questo non è davvero possibile. Avrai bisogno di passare il T "concreta" in qualche modo come metodo di discussione in modo che il tipo effettivo è conosciuta durante il runtime. approccio comunemente usato sta passando come Class<T>, in modo che si può fare uso di Class#cast() :

<T> T getCacheValue(String name, Class<T> type) {
    return type.cast(getServletContext().getAttribute(name));
}

È possibile utilizzare come segue:

Double value = getCacheValue("x", Double.class);

Altri suggerimenti

Mappa generici supportano un tipo su tutti i valori della mappa, non un tipo diverso per i valori specifici. Si può vedere come fingere qui . In sostanza l'idea è che si deve avere la sicurezza di tipo sulla chiave, in cui la chiave è un tipo generico su di esso che esiste semplicemente da associare al valore.

Alla fine della giornata, non sarà in grado di farlo senza un cast non sicuro, ma è possibile farlo in un modo che rende estremamente improbabile che ci sia un problema con un cast e in un modo che è typesafe agli utenti della vostra classe.

In realtà, che compila anche:

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");
    }
}

E 'sorta di inutile (forse se si aggiunge una TYPECHECK), ma ho trovato interessante sapere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top