Groovy将列表强制映射到';t抛出ClassCastException或什么是ArrayList1\u groovyProxy?

Groovy将列表强制映射到';t抛出ClassCastException或什么是ArrayList1\u groovyProxy?,groovy,types,casting,Groovy,Types,Casting,我正在编写代码,试图将一个对象投射到地图上 Map a = object as Map 我也可以使用 Map a = (Map) object 如果对象是List类型的,那么整个问题都无关紧要,因为这会抛出一个ClassCastException,但是通过使用前者,我遇到了一件有趣的事情。 如果对象是一个列表,即对象=[],groovy类型强制的行为将与我预期的不同 我的期望是得到一个ClassCastException,但是我得到了一个结果对象。但这个物体看起来很奇怪。它是List的实例和

我正在编写代码,试图将一个对象投射到地图上

Map a = object as Map
我也可以使用

Map a = (Map) object
如果对象是List类型的,那么整个问题都无关紧要,因为这会抛出一个
ClassCastException
,但是通过使用前者,我遇到了一件有趣的事情。 如果对象是一个列表,即
对象=[]
,groovy类型强制的行为将与我预期的不同

我的期望是得到一个
ClassCastException
,但是我得到了一个结果对象。但这个物体看起来很奇怪。它是List的实例和Map的实例,在其上使用
.toString()
会导致列表而不是Map的输出(
[a,b]
)。此外,也不可能在地图上设置
a['c']='c'
的值。这会导致
java.lang.IllegalArgumentException:参数类型不匹配

Map a = ['a', 'b'] as Map

println(a)
println(a instanceof List)
println(a instanceof Map)
println(a.getClass())
结果如下:

[a, b]
true
true
class ArrayList1_groovyProxy
我试着用谷歌搜索这个
ArrayList1\u groovyProxy
是什么,但什么也找不到

这对我来说仍然没有意义,强制返回的对象显然不是它应该是的对象,而且看起来有点破碎,而不是抛出一个
ClassCastException

有谁能向我解释该行为背后的原因,而不是抛出异常,并解释
ArrayList1\u groovyProxy
?或者这只是groovy中的一个bug?

as调用
asType
方法,并将提供的类型作为该方法的参数

您可以在中看到
asType
的默认实现

由于
Map
是一个接口,它最终将调用
ProxyGenerator.INSTANCE.instanceedelegate(interfaces,obj)
,它返回一个实现
Map
的动态代理

/**
 * Converts a given object to a type. This method is used through
 * the "as" operator and is overloadable as any other operator.
 *
 * @param obj  the object to convert
 * @param type the goal type
 * @return the resulting object
 * @since 1.0
 */
@SuppressWarnings("unchecked")
public static <T> T asType(Object obj, Class<T> type) {
    if (String.class == type) {
        return (T) InvokerHelper.toString(obj);
    }

    // fall back to cast
    try {
        return (T) DefaultTypeTransformation.castToType(obj, type);
    }
    catch (GroovyCastException e) {
        MetaClass mc = InvokerHelper.getMetaClass(obj);
        if (mc instanceof ExpandoMetaClass) {
            ExpandoMetaClass emc = (ExpandoMetaClass) mc;
            Object mixedIn = emc.castToMixedType(obj, type);
            if (mixedIn != null)
                return (T) mixedIn;
        }
        if (type.isInterface()) {
            try {
                List<Class> interfaces = new ArrayList<Class>();
                interfaces.add(type);
                return (T) ProxyGenerator.INSTANCE.instantiateDelegate(interfaces, obj);
            } catch (GroovyRuntimeException cause) {
                // ignore
            }
        }
        throw e;
    }
/**
*将给定对象转换为类型。此方法通过以下方式使用:
*“as”运算符,并且与任何其他运算符一样可以重载。
*
*@param obj要转换的对象
*@param type目标类型
*@返回结果对象
*@自1.0以来
*/
@抑制警告(“未选中”)
公共静态T asType(对象对象对象,类类型){
if(String.class==类型){
返回(T)InvokerHelper.toString(obj);
}
//退却
试一试{
return(T)DefaultTypeTransformation.castToType(obj,type);
}
catch(GroovyCastException e){
元类mc=InvokerHelper.getMetaClass(obj);
if(ExpandoMetaClass的mc实例){
ExpandoMetaClass emc=(ExpandoMetaClass)mc;
Object mixedIn=emc.castToMixedType(obj,type);
if(mixedIn!=null)
回流(T)混合;
}
if(type.isInterface()){
试一试{
列表接口=新的ArrayList();
接口。添加(类型);
return(T)ProxyGenerator.INSTANCE.instanceedelegate(interfaces,obj);
}捕获(GroovyRuntimeException原因){
//忽略
}
}
投掷e;
}

至于为什么Groovy要花这么多时间强制类型——这基本上是Groovy的本质:让Java编码更容易。你可以通过,甚至可以构造一个对象;那么为什么不让每个对象通过
As
操作符被强制回到
映射中呢?

['a',b']
是一个
列表
。如果你想要一个映射,那么定义
defmap=['1':'1','2':'2']
。现在尝试
断言map的map实例
我知道
['a','b']
是一个列表。这不是重点。问题是为什么
['a','b']作为映射
不会引发类似
(map)['a','b']的类异常
有。因为生成的对象似乎非常不可用。不确定,但您在定义时通过说
as Map
强制它。您可以看到
Map a=['a',b']的异常
这是真的,但在我的实际用例中,我还不知道我是否得到了一个列表或其他东西。所以要使用
@CompileStatic
我需要进行强制。这就是为什么在这里会发生这种情况。否则你完全正确,
映射a=object
就足够了。我想返回一个看似损坏的对象,而不是如果这似乎是异常状态,则引发异常。然后,我建议只使用
def variable
。而不是静态类型。使用
if(variable instanceof Map){}else if(variable instanceof List){}
。非常感谢。这就解释了代理类。仍然没有解释为什么它会返回该类,如果它不支持通常的映射操作。我同意,如果可以在构造函数中使用映射来创建所有内容,那么强制将所有内容都返回到映射是可以的,但我们不希望只返回一些内容吗喜欢object.properties吗?