Groovy 的 @CompileStatic 和映射构造函数

标签 groovy

我是第一次使用 @CompileStatic,并且对 Groovy 的映射构造函数在这种情况下如何工作感到困惑。

@CompileStatic
class SomeClass {
    Long id
    String name

    public static void main(String[] args) {
        Map map = new HashMap()
        map.put("id", 123L)
        map.put("name", "test file")
        SomeClass someClass1 = new SomeClass(map) // Does not work
        SomeClass someClass2 = map as SomeClass   // Works
    }
}

鉴于上面的代码,我在尝试编译时看到以下错误

Groovyc:尚未设置构造函数调用表达式的目标构造函数

如果删除@CompileStatic,则两个构造函数都可以正常工作。

谁能解释一下为什么new SomeClass(map)不能用@CompileStatic编译?还有一个可能的补充,为什么map as SomeClass仍然有效?

最佳答案

Groovy 实际上为您提供“ map 构造函数”。构造函数 在你的类里面就是你写下来的。如果没有(就像你的情况一样), 然后是默认的c'tor。

但是,如果你使用所谓的 map c'tor(或者更确切地说称之为 “通过 map 构建对象”)? groovy的一般做法是这样的:

  • 使用默认c'tor创建一个新对象(这就是原因,为什么 如果只有例如,按 map 构建不再有效 SomeClass(Long id, String name) )
  • 然后使用传递下来的映射并将所有值应用到属性。

如果你反汇编你的代码(使用@CompileDynamic(默认))你会看到, 施工由 CallSite.callConstructor(Object,Object) 处理, 归结为这个 code area .

现在引入这个通过 map 构建的版本,这是更熟悉的 对于普通的 Groovyist 来说: SomeClass someClass3 = new SomeClass(id: 42L, name: "Douglas") .

使用动态版本的代码,反汇编看起来实际上 很像你的 map 代码。 Groovy 根据参数创建一个映射并 发送至callConstructor - 所以这实际上是相同的代码路径 采取(减去隐式 map 创建)。

现在忽略“cast-case”,因为它对于静态和静态实际上是相同的 动态:将发送至ScriptBytecodeAdapter.asType基本上 在任何情况下都能为您提供动态行为。

现在是@CompileStatic案例:正如您所目睹的,您的电话与 c'tor 的显式映射不再有效。这是因为, 从一开始就没有明确的“ map 控制者”。类(class)还在 仅具有默认 c'tor 和静态编译 groovyc现在可以 使用现有的东西(如果在本例中不存在,则不使用)。

怎么样new SomeClass(id: 42L, name: "Douglas")然后?这仍然有效 静态编译!原因是 groovyc展开这个 为你。正如您所看到的,这可以简单地归结为 def o = new SomeClass(); o.setId(42); o.setName('Douglas') :

new           #2  // class SomeClass
dup
invokespecial #53 // Method "<init>":()V
astore_2
ldc2_w        #54 // long 42l
dup2
lstore_3
aload_2
lload_3
invokestatic  #45 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
invokevirtual #59 // Method setId:(Ljava/lang/Long;)V
aconst_null
pop
pop2
ldc           #61 // String Douglas
dup
astore        5
aload_2
aload         5
invokevirtual #65 // Method setName:(Ljava/lang/String;)V

关于Groovy 的 @CompileStatic 和映射构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30767266/

相关文章:

grails - Grails结果集分页

bash - 从 groovy 打印 $PATH - 字符被转义?

java - 在 Groovy 中重新加载类

grails - 在 Grails 中使用动态查找器搜索值

xml - 修改 Groovy 中现有的 xml 文件

groovy - 自定义 gradle 任务中注解的继承

java - 如何使用 JPA Criteria API/Hibernate 按 Case 语句分组

java - org.hibernate.MappingException 在 Grails v3.2.9 中使用 tablePerConcreteClass 继承策略时

groovy - 使用spock测试复杂的JSON字符串条件永远不满足

grails - 具有动态参数的Gorm finder(第2部分)?