有没有办法在eval中调用类方法?

时间:2015-09-24 15:30:24

标签: groovy eval

我正在编写粘贴到基于Web的系统中运行的Groovy脚本。有一个 可用于在此环境中运行的脚本的类,我将其称为BrokenClass。它有一个 错误,它只接受字符串文字作为其第一个参数,但不接受变量 带有一个字符串。所以,这将起作用(它返回一个列表):

BrokenClass.reflist('something', 'name')

但是,如果我尝试使用变量作为第一个参数,我会收到错误:

list_name = 'something'
BrokenClass.reflist(list_name, 'name')

这会生成消息Metadata RefList[something] cannot be accessed

我对BrokenClass没有任何控制权(除了在其上提交错误)。我试着去工作 解决这个问题:

list_name = "foo"
list_call = "BrokenClass.reflist(${list_name}, 'name')"
list_values = Eval.me(list_call)

然而,这会产生错误:

groovy.lang.MissingPropertyException: No such property: BrokenClass for class: Script1

我尝试在我的字符串中添加import,但后来我得到unable to resolve class BrokenClass

有没有办法在eval'd字符串中使用BrokenClass?或者其他一些我没有的方式 考虑解决BrokenClass.reflist中的错误?一个非常长的switch块 因为可能的列表名称会改变。

BrokenClass.reflist的方法签名是:

public static List<Object> reflist(String reflistName, String field);

1 个答案:

答案 0 :(得分:1)

我怀疑BrokenClass.reflist()使用==运算符而不是String.equals()直接或间接地进行了不正确的字符串比较。有关差异的解释,请参阅this文章。

问题

以下是问题的演示:

def a = 'whatever'
def b = 'what' + 'ever'

assert doSomething('whatever') == 'OK'
assert doSomething(a) == 'OK'
assert doSomething(b) == 'ERROR'

def doSomething(String value) {
    if(value.is('whatever')) { // In Java this would be: value == "whatever"
        'OK'
    } else {
        'ERROR'
    }
}

因为它使用引用相等性,在Groovy中由Object.is(Object)方法完成,BrokenClass.reflist()被无意中编码为仅使用字符串文字:所有具有相同值的字符串文字引用相同的字符串实例,导致对True的评估。在运行时使用相同的文字值组成的String不引用相同的String实例。

解决

显然BrokenClass.reflist()应该修复。但您可以使用 interned 字符串解决问题。

def b = 'what' + 'ever'

assert doSomething(b.intern()) == 'OK'

def doSomething(String value) {
    if(value.is('whatever')) { 
        'OK'
    } else {
        'ERROR'
    }
}

如果变量的值与String文字的值匹配,则variable.intern()将返回与匹配文字相同的String实例。这将允许Java ==运算符在您需要时工作。