2015-10-13 65 views
1

的常规问题,如果这是一个错误或功能,但它绝对不直观从Java背景的人来跟踪异常的原因。我不知道不正确的getter

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,它返回了错误的东西。

现在我知道我应该在编写代码时更加自觉和不应该从一个getter返回一个不存在的变量这样的错误。但是有什么办法可以让它不做它以前的做法吗?

编辑

Code in Eclipse after adding @TypeChecked

另外之后加入@TypeChecked,下面会出现误差。它在早些时候正常工作。

Error in Eclipse after adding @TypeChecked

+0

在您的类或方法上使用@TypeChecked注释,在这方面它的行为更像Java。 – cjstehno

+0

不知怎的,现在的问题是,方法名称“getInfo”正在阻止编译器显示错误。 (添加了上述截图。)如果我将'getInfo()'更改为'getInfos()'。它使用'@ TypeChecked'正确给出了错误。 – Mahesha999

回答

2

问题在于如果是getinfo法,这意味着这是一个getter的签名。当你调用一个类的属性(这里是“返回信息”)比隐式groovy使用getter getInfo。这创建了一个无限循环,导致StackOverflowError(因为信息调用getInfo,getInfo调用信息,调用getInfo ...)。如果您在此处使用另一个不存在的属性(即返回foo),您将收到预期的MissingPropertyException。为了避免这种行为,您不应该使用名称匹配不存在的属性来定义getter-Methods。

+0

的确如此,所以没有解决方法让编译器捕获这个错误?我是否将该功能误解为问题? – Mahesha999

+3

我认为通常情况下,您可以通过在Groovy中未定义getter来避免此类问题,除非您确实需要。 Groovy为你定义了所有标准的getter和setter。如果您需要特殊行为,您只需要覆盖它们。 – Roland

1

当您添加一个getter的财产,不管是否存在的属性,需要与运营商[email protected]引用属性。这是直接字段访问操作员,它可以跳过任何获取者并直接访问该属性。如果您不使用操作员,则会一次又一次地调用同一个吸气器,直到您获得StackOverflowError

例如:

def getInfo() { 
    return [email protected] 
} 

参见第6节。2直接字段访问运营商Groovy operator docs多一点。

+0

多数民众赞成听起来精确的解决方法,但如何在myy问题的最后一张图中显示无法使用'@ TypeChecked'制作'withDefault'? – Mahesha999

+0

你不需要'@ TypeChecked'。一旦你添加了它,它就会指出你的代码不适合你的想法。你认为你正在递增一个数字,但是真的是在对象上调用next() - 删除'@ TypeChecked',我认为你不会得到你想要的。 – doelleri

相关问题