简介
本文将介绍Groovy中def关键字。它为这种动态 JVM 语言提供了可选的类型化功能。
def关键字的含义
def关键字用于在 Groovy 中定义无类型变量或函数,因为它是一种可选类型的语言。
当我们不确定变量或字段的类型时,我们可以利用 def 让 Groovy 在运行时根据分配的值决定类型:
def a = "FunTester"
def b = ['A', 'B', 'C', 'D']
在这里,a将是一个String,而b将是一个ArrayList。
我们还可以使用def关键字来定义方法的返回类型:
def plus(x, y) {
return x + y
}
在这里,plus可以返回任何类型的对象,这取决于我们传递给它的参数。
因为Groovy可以重载操作符 + ,让对象也可以使用 + 。
def变量
让我们了解def如何处理变量。
当我们使用def声明变量时,Groovy 将其声明为 NullObject并为其分配空值:
def list
assert list.getClass() == org.codehaus.groovy.runtime.NullObject
assert list.is(null)
当我们为列表赋值时,Groovy 会根据赋值定义它的类型:
list = [1,2,4]
assert list instanceof ArrayList
假设我们想让我们的变量类型动态化并随着赋值而改变:
int rate = 20
rate = [12] // GroovyCastException
rate = "nill" // GroovyCastException
我们不能将List或String分配给int类型的变量。为了克服这个问题并调用 Groovy 的动态特性,我们将使用def关键字:
def rate
assert rate == null
assert rate.getClass() == org.codehaus.groovy.runtime.NullObject
rate = 12
assert rate instanceof Integer
rate = "Not Available"
assert rate instanceof String
rate = [1, 4]
assert rate instanceof List
def方法
def关键字进一步用于定义方法的动态返回类型。当我们可以为一个方法提供不同类型的返回值时,使用Groovy def很方便:
def divide(int x, int y) {
if (y == 0) {
return "被除数不能为 0"
} else {
return x/y
}
}
assert divide(12, 3) instanceof BigDecimal
assert divide(1, 0) instanceof String
我们还可以使用def来定义一个没有显式返回的方法:
def greetMsg() {
println "Have Fun ~ Tester !"
}
def与Type
让我们讨论一些围绕使用def的最佳实践。
虽然我们可以在声明变量时同时使用 def 和 type:
def int count
assert count instanceof Integer
def关键字在那里是多余的,所以我们应该使用def或具体的类型。此外我们应该尽量避免方法参数中使用def关键字。虽然这有时候用起来很爽,很高效,但是埋下的坑总归是要还的。
不适合的示范:
void multiply(def x, def y)
最佳示范:
void multiply(x, y)
此外,我们应该避免在构造函数时使用def。
Groovy def 与 Java Object
由于我们已经了解了def关键字的大部分功能及其用法,可能大多数人都在会问:它是否类似于在 Java 中使用Object类声明某些内容。def可以被认为类似于Object:
def fullName = "Norman Lewis"
同样,我们可以在 Java 中使用Object :
Object fullName = "Norman Lewis";
def与@TypeChecked
如果你是一个Java技术栈选手,你可能想知道如何在 Groovy 中强制进行编译时类型检查。我们可以使用@TypeChecked注释轻松实现这一点。
例如,我们可以在一个类上使用@TypeChecked来为其所有方法和属性启用类型检查:
@TypeChecked
class FunTester extends GroovyTestCase {
def multiply(x, y) {
return x * y
}
int divide(int x, int y) {
return x / y
}
}
在这里,FunTester类将被类型检查,编译代码时将会报错:
[Static type checking] - Cannot find matching method java.lang.Object#multiply(java.lang.Object). Please check if the declared type is correct and if the method exists.
如果你想要忽略一个方法,我们可以使用TypeCheckingMode.SKIP:
@TypeChecked(TypeCheckingMode.SKIP)
def multiply(x, y)