Contents

Groovy中Def关键字

1. 概述

在这个快速教程中,我们将探讨Groovy中 def关键字的概念。它为这种动态 JVM 语言提供了一个可选的类型功能。

2. def关键字的含义

def关键字用于在 Groovy 中定义无类型变量或函数,因为它是一种可选类型语言。

当我们不确定变量或字段的类型时,我们可以利用def让 Groovy 在运行时根据分配的值决定类型:

def firstName = "Samwell"  
def listOfCountries = ['USA', 'UK', 'FRANCE', 'INDIA']

在这里,firstName将是一个String,而listOfCountries将是一个ArrayList

我们还可以使用def关键字来定义方法的返回类型:

def multiply(x, y) {
    return x*y
}

在这里,multiply可以返回任何类型的对象,具体取决于我们传递给它的参数。

3. def变量

让我们了解def如何对变量起作用。

当我们使用def声明一个变量时,Groovy 将其声明为NullObject 并为其分配一个null值:

def list
assert list.getClass() == org.codehaus.groovy.runtime.NullObject
assert list.is(null)

在我们为list赋值的那一刻,Groovy 根据赋值定义它的类型:

list = [1,2,4]
assert list instanceof ArrayList

假设我们希望我们的变量类型是动态的并通过赋值进行更改:

int rate = 20
rate = [12] // GroovyCastException
rate = "nill" // GroovyCastException

我们不能将ListString分配给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

4. def方法

def关键字进一步用于定义方法的动态返回类型。当我们可以为方法提供不同类型的返回值时,这很方便:

def divide(int x, int y) {
    if (y == 0) {
        return "Should not divide by 0"
    } else {
        return x/y
    }
}
assert divide(12, 3) instanceof BigDecimal
assert divide(1, 0) instanceof String

我们也可以使用def来定义一个没有显式返回的方法:

def greetMsg() {
    println "Hello! I am Groovy"
}

5. def vs. 类型

让我们讨论一些使用def的最佳实践。

虽然我们可以在声明变量时同时使用def和 type :

def int count
assert count instanceof Integer

def关键字在那里是多余的,所以我们应该使用def或类型。**

此外,我们应该避免在方法中对无类型参数使用def

因此,而不是:

void multiply(def x, def y)

我们应该更喜欢:

void multiply(x, y)

此外,我们应该避免在定义构造函数时使用def

6. Groovy  def 与 Java Object

正如我们已经通过示例看到了def关键字的大部分特性及其用法,我们可能想知道它是否类似于在 Java 中使用Object类声明某些东西。是的,def可以被认为类似于Object**:

def fullName = "Norman Lewis"

同样,我们可以在 Java中使用Object

Object fullName = "Norman Lewis";

7. def与*@TypeChecked*

由于我们中的许多人都来自严格类型语言的世界,我们可能想知道如何在 Groovy 中强制进行编译时类型检查。我们可以使用*@TypeChecked*注解轻松实现这一点。

例如,我们可以在一个类上使用*@TypeChecked*来启用对其所有方法和属性的类型检查:

@TypeChecked
class DefUnitTest extends GroovyTestCase {
    def multiply(x, y) {
        return x * y
    }
    
    int divide(int x, int y) {
        return x / y
    }
}

在这里,将对DefUnitTest类进行类型检查,由于multiply方法是 untyped ,编译将失败。Groovy 编译器将显示错误:

[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)