Как Java примитивные классы-оболочки поддерживают дополнительные методы в Groovy? - PullRequest
1 голос
/ 19 апреля 2020

Я родом из 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, который является окончательным. Как это возможно?

1 Ответ

3 голосов
/ 19 апреля 2020

Те методы, которые вы упомянули, называются По умолчанию Groovy Методы , и большинство из них реализованы в классе org.codehaus.groovy.runtime.DefaultGroovyMethods. Такой метод, как intdiv, не добавляется в окончательный класс 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));

Волхвов нет c это просто Groovy компилятор, который знает, как выполнять такие преобразования в дереве абстрактного синтаксиса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...