不正确的吸气剂的常见问题

时间:2015-10-13 12:04:44

标签: groovy

我不知道这是一个错误还是一个功能,但对于跟踪异常原因的Java背景的人来说,这肯定是不直观的。

即使未定义变量,Groovy也允许引用变量。 例如,考虑以下类:

class B {
    def infos;

    public B(String param)
    {
        infos = param
    }

    public getInfo()
    {
        return info;
    }
}

如果您注意到,在getInfo()内,我将返回永远未定义的info。但是,Eclipse没有发出警告。所以我继续写下面的内容:

class A
{
    static main(def args)
    {
        B bObj = new B("Mahesh")

        println "Hello groovy"
        println bObj.getInfo()
        println "Hello groovy"
    }
}

现在这为StackOverflowError提供了一个巨大的堆栈跟踪:

Exception in thread "main" java.lang.StackOverflowError
at java.lang.Exception.<init>(Exception.java:102)
at java.lang.ReflectiveOperationException.<init>(ReflectiveOperationException.java:89)
at java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:72)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3493)
at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.callGroovyObjectGetProperty(GetEffectivePogoPropertySite.java:67)
--> at packages.B.getInfo(ThreadDumpsExp.groovy:169)  <--
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3493)
at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.callGroovyObjectGetProperty(GetEffectivePogoPropertySite.java:67)
      :
      :

此处的堆栈跟踪是正常的,因为堆栈跟踪中的某处向下指向此特定行,我在上面的堆栈跟踪中用箭头突出显示。我期待堆栈跟踪中的这一行,这就是我能够快速跟踪它的原因。这个问题出现了,今天我在我的项目中遇到了同样的问题。堆栈跟踪同样巨大。我不知道它实际上出了什么问题,所以我无法猜测哪条线可能实际上是错误的。最糟糕的是它在调试期间停止在Groovy的源代码中。我不得不反复在不同的地方放置断点来实际停止执行它们。一段时间后,我发现调试器实际停在我的代码中的行。从那里我逐步完成整个代码,找到导致问题的那一行。这条线是一个简单的吸气剂,它返回了错误的东西。

现在我知道在编写代码时我应该更有意识,并且不应该犯这样的错误,即从getter返回一个不存在的变量。但有没有办法让它不做上面做的事情?

修改

Code in Eclipse after adding @TypeChecked

此外,在添加@TypeChecked后,会出现以下错误。它之前的工作正常。

Error in Eclipse after adding @TypeChecked

2 个答案:

答案 0 :(得分:2)

问题在于getInfo-Method的签名,这意味着这是一个getter。当你调用一个类的属性(这里用&#34;返回信息&#34;)而不是隐式groovy使用getter getInfo。这会创建一个无限循环,导致StackOverflowError(因为info调用getInfo,getInfo调用info,调用getInfo ...)。如果你在这里使用另一个不存在的属性(即return foo),你会收到预期的MissingPropertyException。为避免此行为,您不应定义名称与不存在的属性匹配的getter-Methods。

答案 1 :(得分:2)

为属性添加getter时,无论属性是否存在,都需要使用.@运算符引用该属性。这是直接的现场访问操作员,它跳过任何吸气剂并直接前往酒店。如果您不使用运算符,则会反复调用相同的getter,直到获得StackOverflowError

例如:

def getInfo() {
    return this.@info
}

请参阅Groovy operator docs中的第6.2节直接字段访问运算符以获取更多信息。