gpt4 book ai didi

java - 在 Groovy 中将整数转换为 BigDecimal

转载 作者:行者123 更新时间:2023-11-30 10:20:18 25 4
gpt4 key购买 nike

假设我们在 groovy 中有一个函数将 BigDecimal 作为参数:

 void func(BigDecimal bd) {...}

然后在 groovy 的其他类中再次调用它 var.func(0)

这工作正常,但在 java 中它根本无法编译。我知道 BigDecimal 中有一个构造函数适用于 Integer,但它在 groovy 中有效并且 java 提示它的原因是什么?是否有将 def 变量转换为 java 中已知的东西?

最佳答案

当您使用不同于声明类型的值调用方法时,Groovy 使用参数类型强制。如果是 BigDecimal 参数类型强制 Groovy 使用 BigDecimalCachedClass.coerceArgument(Object argument)方法:

public Object coerceArgument(Object argument) {
if (argument instanceof BigDecimal) {
return argument;
} else if (argument instanceof Long) {
return new BigDecimal((Long) argument);
} else if (argument instanceof BigInteger) {
return new BigDecimal((BigInteger) argument);
}

if (argument instanceof Number) {
return new BigDecimal(((Number) argument).doubleValue());
}
return argument;
}

当您将 Integer 作为参数传递时,if (argument instanceof Number) 分支得到满足,Groovy 将输入 Integer 转换为其 BigDecimal代表。

它在 Java 中不起作用,因为 Java 不是动态语言,所以所有类型都必须在编译时解析。 Groovy 支持动态类型,因此您的最终类型可以在运行时解析。

@CompileStatic@TypeChecked

Groovy 允许您关闭它的动态特性。如果您使用 @CompileStatic@TypeChecked 注释您的类,那么调用 var.func(0) 将不再有效,因为 Groovy 将不再使用它的动态特性。

考虑以下简单的 Groovy 类:

class NumTest {

static void main(String[] args) {
test(20)
}

static void test(BigDecimal number) {
println number
}
}

当你用 groovyc 编译它时,你会看到一个像这样的 Java 类:

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

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import java.math.BigDecimal;
import org.codehaus.groovy.runtime.callsite.CallSite;

public class NumTest implements GroovyObject {
public NumTest() {
CallSite[] var1 = $getCallSiteArray();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}

public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].callStatic(NumTest.class, Integer.valueOf(20));
}

public static void test(BigDecimal number) {
CallSite[] var1 = $getCallSiteArray();
var1[1].callStatic(NumTest.class, number);
}
}

有趣的是,调用 test(20) 不是直接的静态方法调用,而是:

var1[0].callStatic(NumTest.class, Integer.valueOf(20));

但是如果我们用 @CompileStatic 注释我们的类,它将不再编译,我们将不得不用直接 test( BigDecimal.valueOf(20)) 调用:

import groovy.transform.CompileStatic

@CompileStatic
class NumTest {

static void main(String[] args) {
test(BigDecimal.valueOf(20))
}

static void test(BigDecimal number) {
println number
}
}

groovyc编译这个类生成完全不同的Java类:

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

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import java.math.BigDecimal;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;

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

public static void main(String... args) {
test(BigDecimal.valueOf((long)20));
Object var10000 = null;
}

public static void test(BigDecimal number) {
DefaultGroovyMethods.println(NumTest.class, number);
Object var10000 = null;
}
}

这里可以看到直接调用了test(BigDecimal.valueOf((long)20));方法,所以没有类型强制,必须传递有效类型到位。

关于java - 在 Groovy 中将整数转换为 BigDecimal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48296049/

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