使用@CompileStatic和@Newify时的GroovyCastException

时间:2016-02-17 08:08:15

标签: groovy

为什么下面的代码会提供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.newnew B替换,则上面的代码不会出现异常并按我的预期运行。 Groovy的版本是2.4.5。

1 个答案:

答案 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;
}