2012-04-10 14 views
5

Estoy buscando una forma de crear un HashMap que se correlacione con tipos mixtos.Java Mapeo de tipos mixtos

Por ejemplo, la siguiente funcionaría en Python (nótese que una pitón dict es similar a una de Java HashMap):

d = dict() 
d["str"] = "This is a string" 
d["flt"] = 1.23 
d["int"] = 5 

y cuando se accede a d[x], se devolvería el tipo apropiado (cadena, flotador, int en este ejemplo).

En Java, podría ir con un HashMap<String, Object>, pero realmente no tengo una forma de decir inmediatamente de qué tipo es cada objeto.

Por el contrario, lo que intento hacer es crear una clase MixedType que contenga un objeto, pero también su información de tipo original, para que pueda descifrarlo más tarde. Por ejemplo:

public class MixedMap 
    public static class MixedType 
    { 
     public Class<?> cls; 
     public Object val; 

     public MixedType(Class<?> c, Object v) 
     { 
      this.cls = c; 
      this.val = v; 
     } 
    } 

    public static void main(String args[]) 
    { 
     MixedType m1 = new MixedType(String.class, "This is a String"); 
     System.out.println((m1.cls)m1.val); 
    } 
} 

Tenga en cuenta que esto es lo que estoy tratando hacer :-) ya que es en este momento no se queja de que la compilación m1 cannot be resolved to a type.

Entonces mi pregunta es, ¿cómo puedo solucionar esto? Otras formas de lograr el mismo objetivo serían bienvenidas, pero no responda diciéndome que esto limita la capacidad de verificación de tipos del compilador: lo sé y estoy de acuerdo con eso.

Gracias de antemano.

+2

¿Puedo preguntar: ¿qué harás con los objetos una vez recuperados? Siento que normalmente hay una mejor manera de diseñar esto para evitar tener que lanzar en absoluto. –

+1

Incluso si tiene información de tipo almacenada en sus 'objetos' simples, ¿cómo espera saber qué hacer después de lanzarlos? –

+0

Claro, usaré el HashMap como un objeto de tipo "configuración", donde el usuario especificará ciertos ajustes de configuración que serán analizados y colocados en este mapa. En ciertos puntos del programa verificará si se establece una determinada opción de configuración; si es así, úsala y, si no, utiliza la predeterminada. La razón de la necesidad de tipos mixtos es que algunas opciones de configuración sean cadenas, otras flotantes, otras entradas, etc. – jedwards

Respuesta

6

Lo correcto es m1.cls.cast(m1.val), pero es casi seguro que no obtendrá nada en comparación con un simple Map<String, Object>. Un enfoque más simple que le proporcionará exactamente la misma seguridad y la misma información, es decir, no mucho, sería simplemente utilizar el método getClass() en los valores Object en su mapa.

Nada de esto logrará su objetivo de poder decir String value = map.get("str") - nada menos que un elenco directo haría eso. Puede hacer

Object value = map.get("str"); 
if (value instanceof String) { 
    // do stringy things 
} 

o algo similar.

Si conoce los tipos de los valores en sus puntos de uso en el momento de la compilación, entonces, de lejos, la mejor solución es seguir adelante y hacer los moldes en los puntos de uso. La forma "ideal" de hacer una configuración como esta en general no es usar un Map, sino construir una clase personalizada Configuration que conozca sus campos y sus tipos en tiempo de compilación, pero si desea usar un Map, simplemente haga lo lanzar directamente es probablemente tu mejor apuesta.

+0

¡Gracias por las numerosas soluciones alternativas! – jedwards

1

He implementado algo similar a esto antes. Puede usar genéricos para ayudar. Lo que quiere es un MixedKey, que puede usar como clave en un MixedMap. Algo en esta línea:

public class MixedKey<T> { 
    public final Class<T> cls; 
    public final String key; 

    public MixedKey(T cls, String key) { 
     this.key = key; 
     this.cls = cls; 
    } 

    // also implement equals and hashcode 
} 

.

public class MixedMap extends HashMap<MixedKey<?>,Object> { 
    public <T> T putMixed(MixedKey<T> key, T value) { 
     return key.cls.cast(put(key, value)); 
    } 

    public <T> T getMixed(MixedKey<T> key) { 
     return key.cls.cast(get(key)); 
    } 
} 

Lo bueno de hacer algo como esto es que le dará un error en tiempo de compilación si se utiliza el tipo equivocado por error, algo que no se consigue con colada directa:

MixedKey<Integer> keyForIntProperty 
    = new MixedKey<Integer>(Integer.class, "keyForIntProperty"); 

// ... 

String str = mixedMap.getMixed(keyForIntProperty); // compile-time error 

vs.

String str = (String)map.get("keyForIntProperty"); // run-time error only 
Cuestiones relacionadas