首页 > 解决方案 > Java 原始包装类如何支持 Groovy 中的其他方法?

问题描述

我来自 Java 背景,现在我正在学习 Groovy。以下代码是有效的 Groovy 代码。

def val=1
println val.getClass() //will print java.lang.Integer
def ans=3.intdiv(2)    //performs integer division

我想知道,Groovy 是如何将这样的方法添加intdiv到最终java.lang.Integer类的?还有很多其他这样的方法,如times, upto, downto, step, 等等。这些方法被添加到最终的 Java 类中。这怎么可能?

标签: javagroovy

解决方案


您提到的那些方法称为默认 Groovy 方法,它们中的大多数都在org.codehaus.groovy.runtime.DefaultGroovyMethods类中实现。likeintdiv方法不会添加到最终Integer类中,而是Number在默认 Groovy 方法中为任何类实现。现在,当 Groovy 编译器将 Groovy 代码编译为字节码时,它会检测到类似的2.intdiv(3)内容,并将这个表达式替换为类似的内容DefaultGroovyMethods.intdiv(2,3)

为了使这个插图更加清晰,请看下面的 Groovy 类:

import groovy.transform.CompileStatic

@CompileStatic
class SomeClass {

    static void main(String[] args) {
        def val=1
        println val.getClass()
        def ans = 3.intdiv(2)
        println ans
    }
}

当您将其编译为SomeClass.class文件,然后将其反编译为 Java(例如,通过在 IntelliJ IDEA 中打开此类文件),您将看到以下 Java 类等价物:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import groovy.transform.Internal;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;

public class SomeClass implements GroovyObject {
    @Generated
    public SomeClass() {
        MetaClass var1 = this.$getStaticMetaClass();
        this.metaClass = var1;
    }

    public static void main(String... args) {
        int val = 2;
        int some = DefaultTypeTransformation.intUnbox(DefaultGroovyMethods.intdiv(Integer.valueOf(val), 3));
        DefaultGroovyMethods.println(SomeClass.class, some);
        Object var10000 = null;
    }

    @Generated
    @Internal
    public MetaClass getMetaClass() {
        MetaClass var10000 = this.metaClass;
        if (var10000 != null) {
            return var10000;
        } else {
            this.metaClass = this.$getStaticMetaClass();
            return this.metaClass;
        }
    }

    @Generated
    @Internal
    public void setMetaClass(MetaClass var1) {
        this.metaClass = var1;
    }
}

你可以看到

def ans = 3.intdiv(2)

变成

int some = DefaultTypeTransformation.intUnbox(DefaultGroovyMethods.intdiv(Integer.valueOf(val), 3));

没有魔法,只有 Groovy 编译器知道如何在抽象语法树上进行这种转换。


推荐阅读