java - 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 类中。这怎么可能?
解决方案
您提到的那些方法称为默认 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 编译器知道如何在抽象语法树上进行这种转换。
推荐阅读
- javascript - 如何为 Openlayers 切换器添加 KML 层?
- cypress - 赛普拉斯 - 测试重定向
- mongodb - 在 Ubuntu 20.04 上启用多个 mongodb 实例
- wpf - 如何离线使用 Windows.Media.SpeechRecognition?
- angular - 我应该使用 Spring 安全角色基础授权还是 Angular Route Gards 或两者兼而有之?
- ethereum - 警告!合约执行过程中遇到的错误 [Reverted] = EIP 1559 之后的ETH主链
- android - Android 中 KEYCODE_APP_SWITCH 的 HID 用法?
- firebase - 如何通过 gcloud 将 tflite 文件上传到 firebase 测试实验室设备?
- scala - 当 NullType 在 StructType 中时,将空值写入 Spark 中的 Parquet
- java - pdfbox:java.lang.NumberFormatException:对于输入字符串:“1#1”