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