gpt4 book ai didi

映射的 Groovy AS 关键字 > 类绑定(bind)

转载 作者:行者123 更新时间:2023-12-01 15:43:10 28 4
gpt4 key购买 nike

给定以下类:

class A {
B b
int data
int data2
}
class B {
C c
String data
}
class C {
Date data
}

代码工作正常:
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

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

但!如果我“拼错”属性名称,例如:
def a = [ data:42, data22:84, b:[ data:'BBB', c:[ data:now ] ] ] as A

我越来越

java.lang.NullPointerException: Cannot get property 'c' on null object



我看到的是只有 A类使用无参数构造函数实例化, bc属性都是 null s。

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

因此有2个问题:
  • (相当哲学)。这是预期的行为吗?不应该跳过拼写错误的 Prop 吗?
  • as怎么可能关键字被设为“宽松”以跳过未知 Prop ?

  • TIA

    更新:

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

    最佳答案

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

    <A@7bab3f1a b=B@1e1a0406 data=42 data2=84>

    但是,如果您将未由类字段表示的条目放入映射中,则 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>

    这个代理根本不初始化字段,但是它将你的映射存储为一个内部的 $closures$delegate$map。 field 。

    看看我使用您的示例进行的以下分析。
  • DefaultGroovyMethods.asType(Map map, Class<?> clazz)内部抛出 GroovyCastException
    org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '{data=42, data22=84, b={data=BBB, c={data=Fri Dec 20 12:22:28 CET 2019}}}' with class 'java.util.LinkedHashMap' to class 'A' due to: org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack: No such property: data22 for class: A
    Possible solutions: data2, data

    来源:https://github.com/apache/groovy/blob/GROOVY_2_5_8/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java#L11813
  • 捕获异常并调用回退方法:
    return (T) ProxyGenerator.INSTANCE.instantiateAggregateFromBaseClass(map, clazz);

    来源:https://github.com/apache/groovy/blob/GROOVY_2_5_8/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java#L11816
  • ProxyGenerator初始化 ProxyGeneratorAdapter在以下方法中:
    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces, Class clazz, Object[] constructorArgs) {
    if (clazz != null && Modifier.isFinal(clazz.getModifiers())) {
    throw new GroovyCastException("Cannot coerce a map to class " + clazz.getName() + " because it is a final class");
    }
    Map<Object,Object> map = closureMap != null ? closureMap : EMPTY_CLOSURE_MAP;
    ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, null, clazz);

    return adapter.proxy(map, constructorArgs);
    }

    来源:https://github.com/apache/groovy/blob/GROOVY_2_5_8/src/main/groovy/groovy/util/ProxyGenerator.java#L162

    此方法可能存在错误:在 createAdapter(map, interfaces, null, clazz)部分,null值代表delegatingClass目的。当它为空时,在生成的代理类中没有应用委托(delegate)机制。
  • 最后但同样重要的是,adapter.proxy(map, constructorArgs)实例化一个新对象,其字符串转储表示如下所示:
    <A1_groovyProxy@537f60bf $closures$delegate$map=[data:42, data22:84, b:[data:BBB, c:[data:Fri Dec 20 13:29:06 CET 2019]]] b=null data=0 data2=0>

    如您所见,传递给构造函数的映射存储为 $closure$delegate$map field 。全部 A类值以其默认值初始化(null 用于 b 字段,0 用于剩余的 int 字段。)
  • 现在,ProxyGenerator类有一个创建支持委托(delegate)的适配器的方法:
    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate, Class baseClass, String name) {
    Map<Object,Object> map = closureMap != null ? closureMap : EMPTY_CLOSURE_MAP;
    ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, delegate.getClass(), baseClass);

    return adapter.delegatingProxy(delegate, map, (Object[])null);
    }

    来源:https://github.com/apache/groovy/blob/GROOVY_2_5_8/src/main/groovy/groovy/util/ProxyGenerator.java#L203

    我猜如果 ProxyGeneratorAdapter带有非空 delegatingClass被使用,调用 a.b将使用内部委托(delegate)映射中的值,而不是 b字段值。这只是我的假设。

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

    关于映射的 Groovy AS 关键字 > 类绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59423991/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com