Convertire file Java codice legacy a generiche - come sostituire oggetto con il tipo?
-
03-10-2019 - |
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 ??em> 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?
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.