为什么下面的代码会提供GroovyCastException
?
class Main {
public static void main(String... args) {
Test test = new Test()
}
}
@CompileStatic @Newify
class Test {
private HashMap<String, A> hashMap = [:]
public Test() {
set()
test()
}
public void test() {
hashMap.each() { String string, A a ->
a.printString()
}
}
public void set() {
hashMap.put("aaa", B.new("xxx"))
hashMap.put("bbb", B.new("yyy"))
}
}
class A {
public String string = ""
public void printString() {
println(string)
}
}
class B extends A {
public B(String string) {
this.string = string
}
}
堆栈跟踪是:
Exception in thread "main" org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'main.Test@543e710e' with class 'main.Test' to class 'main.A'
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:405)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:319)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:232)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:603)
at main.Test$_test_closure1.doCall(Main.groovy:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1019)
at groovy.lang.Closure.call(Closure.java:426)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.callClosureForMapEntry(DefaultGroovyMethods.java:5226)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2107)
at main.Test.test(Main.groovy:36)
at main.Test.<init>(Main.groovy:32)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:80)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:239)
at main.Main.main(Main.groovy:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
但是,如果省略@CompileStatic
,或省略@Newify
并且B.new
被new B
替换,则上面的代码不会出现异常并按我的预期运行。
Groovy的版本是2.4.5。
答案 0 :(得分:0)
这可能是groovy中的一个错误。您应该在JIRA上打开一个问题。
如果我反编译Test.test闭包,我看到:
public Object doCall(String string, A a) {
((A)ScriptBytecodeAdapter.castToType(((_test_closure1)this).getThisObject(), A.class))
.printString();
return null;
}
Groovy尝试转换&#39;这个&#39;到A,而不是变量a。
没有@Newify
,生成是正确的:
public Object doCall(String k, A a) {
a.printString();
return null;
}