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;
}
当您将一个整数作为参数传递时,
if(argument instanceof Number)
分支被满足,并且Groovy将输入的整数转换为其
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的类:
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))
替换test(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类:
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));
方法,因此没有类型强制转换,您必须传递一个有效的类型。
def
类似于Java中的Object
,但是这个问题对我来说不太清楚... - daggett