2012-03-05 67 views
0

我有一个完整的stumper,并将其提供给所有人,看看你是否知道发生了什么事情。未能强制在Java通用类型

这是数据结构

Map<String, Object> objectMap 

它存储字符串和数值现在,但可能在未来存储更多类型。

这是我用来检索这些值的函数:

public <T> T get(String variable, T defaultValue) { 
    // returns either the object from the map, or the default if its not in the map. 
    Object value = getObject(variable, defaultValue); 
    logger.debug("default value is of type " + defaultValue.getClass().getName()); 

    // Attempt to get around casting issue 
    if (value instanceof Number) 
    { 
     value = (Number) value; 
    } 
    T ret = (T) value; 
    logger.debug("Variable " + variable + " which is of type " + value.getClass().getName() + " and returning as " + ret.getClass().getName() + " (is number: " + (value instanceof Number) + ")"); 

    return ret; 
} 

这是调用代码:

public int getFoo() { return this.<Integer>get("foo", 0); } 

这是输出我在日志中看到:

default value is of type java.lang.Integer 
Variable foo which is of type java.lang.Long and returning as java.lang.Long (is number: true) 

就在它失败之前:

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer 

这里最让我担心的是类的类型看起来很长,尽管试图强制类使用Integer

我错过了什么,或者违反了Java泛型的一些概念?

感谢所有帮助

+0

对于初学者,你真的不应该使用'Map '。地图应该有一个单一的,具体的价值类型,它真的是有代码的臭混合在一起。 – 2012-03-05 08:14:02

+0

请发送更多堆栈跟踪,发生此异常? – MJM 2012-03-05 08:18:40

+0

对地图的看法是什么? – 2012-03-05 08:19:21

回答

1

getObject方法返回的值为java.lang.Long - 日志告诉你。泛型不是魔术,它们不会在类型之间进行转换,它们只是编译器转换为强制转换的语法糖。所以,你的方法:

public <T> T get(String variable, T defaultValue) 

是真的:

this.<Integer>get("foo", 0) 

这是真的:

(Integer)this.get("foo", 0) 

因此,ClassCastException异常

public Object get(String variable, Object defaultValue) 

当get方法与调用因为返回的是Long,而不是Integer

不知道你想要达到什么目的很难给出具体的建议,但通常你的Map应该使用你期望处理的泛型类型。在你的情况下,这听起来像IntegerNumber。如果你真的需要任何Number的int值(我怀疑是因为值大于int时会被截断),那么你应该使用Number.intValue()方法。

+0

这是我一直在寻找的anser。我想到了这一点。 强制函数中的类型变为整数,而不是成为一个表演。 – cyberconte 2012-03-05 08:59:36

+0

当呼叫正在执行时,这。 get(“foo”,0) 被转换为(Integer)this.get(“foo”,0)。但即使是动态的,这种转换也不如泛型所执行的那样:在方法实现中可以进一步转换。 – DaveFar 2012-03-05 12:40:00

0

这是由Java类型擦除造成的。 Java类型仅用于源代码。编译器会转换代码,就好像您要投射所有对象一样。如果您获得Long值,则表示您将其作为Long值。

此代码不能执行任何东西:

if (value instanceof Number) 
{ 
    value = (Number) value; 
} 
0

在底层映射中的关键“富”的值是Long类型明显。你不能将Long转换为Integer(即使它们都是Number类型 - 都是Object类型)

如果你想强制一个Integer,你必须在将“foo”进入地图。