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

Is there a way to call a class method inside an eval?

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

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 字符串中使用 BrokenClass?或者我没有的其他方式 是否考虑解决 BrokenClass.reflist 中的错误?一个很长的 switch 块 已经出来了,因为可能的列表名称发生了变化。

BrokenClass.reflist 的方法签名是:

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

我怀疑 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() 无意中编码为仅适用于字符串文字:所有字符串文字具有相同的value 引用相同的 String 实例,导致计算结果为 True。在 运行 时间组成的具有相同文字值的 String 不引用相同的 String 实例。

解决方法

显然 BrokenClass.reflist() 应该修复。但是您可以使用 interned String.

解决此问题
def b = 'what' + 'ever'

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

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

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