用于 Map > 类绑定的 Groovy AS 关键字

inj*_*eer 5 groovy casting

给定以下课程:

class A {
    B b
    int data
    int data2
}
class B {
    C c
    String data
}
class C {
    Date data
}
Run Code Online (Sandbox Code Playgroud)

该代码工作正常:

Date now = new Date()
def a = [ data:42, data2:84, b:[ data:'BBB', c:[ data:now ] ] ] as A
assert a.b.c.data == now
assert a.data == 42
assert a.data2 == 84
Run Code Online (Sandbox Code Playgroud)

现在,如果我省略data2:84,代码仍然可以正常工作,当然除了最后一个assert

但!如果我“拼错”属性名称,例如:

def a = [ data:42, data22:84, b:[ data:'BBB', c:[ data:now ] ] ] as A
Run Code Online (Sandbox Code Playgroud)

我越来越

java.lang.NullPointerException:无法获取空对象上的属性“c”

我看到的是,只有A类是用无参数构造函数实例化的,并且b属性c都是nulls。

所以,跳过!=拼写错误。

因此有两个问题:

  1. (相当哲学)。这是预期的行为吗?拼写错误的 props 不应该被跳过吗?

  2. 如何as使关键字变得“宽松”以跳过未知的道具?

TIA

更新:

创建 JIRA 任务https://issues.apache.org/jira/browse/GROOVY-9348

Szy*_*iak 4

有一个主要区别。当您使用包含现有类字段的映射构造函数时,A将初始化常规对象。这是println a.dump()在这种情况下产生的结果。

<A@7bab3f1a b=B@1e1a0406 data=42 data2=84>
Run Code Online (Sandbox Code Playgroud)

但是,如果您将不由类字段表示的条目放入映射中,Groovy 不会初始化A对象,而是创建类的代理A

<A1_groovyProxy@537f60bf $closures$delegate$map=[data:42, data22:84, b:[data:BBB, c:[data:Fri Dec 20 13:39:50 CET 2019]]] b=null data=0 data2=0>
Run Code Online (Sandbox Code Playgroud)

该代理根本不初始化字段,但它将使用构造函数传递的映射存储为内部$closures$delegate$map字段。

看看我用你的例子所做的以下分析。

问题是:这是一个错误吗?这取决于。正如 cfrick 在评论之一中提到的,A使用不正确的映射进行初始化会引发显式错误,然后您就完成了。这里这个异常被抑制了,从调用者的角度来看,你不知道后台发生了什么。我使用 Groovy 2.5.8 和 3.0.0-RC1 运行这些测试,两个版本中的行为相同。报告这是 Apache Groovy JIRA 项目中的一个问题听起来很合理,因此您可以从 Groovy 核心维护人员那里获得反馈。