1. Groovy变量基础入门
作为一门运行在JVM上的动态语言,Groovy的变量系统既保留了Java的强类型特性,又提供了动态类型的灵活性。与Java不同,Groovy中声明变量时类型是可选的,这种设计让代码更加简洁,同时保留了类型安全的好处。
1.1 变量声明方式
Groovy支持三种变量声明语法:
groovy复制// 显式类型声明(静态类型)
String explicitType = "Hello"
// 使用def关键字(动态类型)
def dynamicVar = 42
// 无类型声明(动态类型)
untypedVar = 3.14
实际开发中最推荐使用def关键字,它既保持了代码可读性,又提供了类型灵活性。显式类型声明适合需要严格类型约束的场景,而无类型声明容易造成代码可维护性问题。
类型推导是Groovy变量的重要特性。当使用def时,Groovy会根据赋值内容自动推断类型:
groovy复制def a = 1 // Integer
def b = 'text' // String
def c = [] // ArrayList
1.2 变量作用域
Groovy的作用域规则与Java类似但更加灵活:
- 无修饰符:类似Java的default作用域
- @Field注解:将局部变量提升为类字段
- private/protected/public:与Java相同
groovy复制class ScopeExample {
def classField = "类字段"
void method() {
def localVar = "局部变量"
println classField // 可访问
}
void anotherMethod() {
println localVar // 编译错误!
}
}
作用域陷阱:在脚本中直接声明的变量实际上会成为脚本类的字段,这与其他语言不同:
groovy复制x = 10 // 实际上是this.x = 10
def printX() {
println x // 可以访问
}
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Groovy基本数据类型详解
Groovy的数据类型系统建立在Java基础上,但进行了许多增强和简化。
2.1 基本数据类型
| 类型 | 说明 | Groovy增强特性 |
|---|---|---|
| int | 整数 | 支持任意进制表示(0x,0b等) |
| float/double | 浮点数 | 支持科学计数法(1.23e4) |
| boolean | 布尔值 | 非布尔值自动转换(非空/非零为true) |
| char | 字符 | 支持多种编码格式 |
| String | 字符串 | 多行字符串、插值字符串 |
Groovy会自动在基本类型和包装类型间转换,解决了Java的自动装箱问题:
groovy复制int i = 123
Integer j = i // 自动装箱
int k = j // 自动拆箱
2.2 字符串处理
Groovy字符串有三种形式:
-
单引号字符串:普通字符串,不支持插值
groovy复制'Hello $name' // 输出字面量Hello $name -
双引号字符串:支持插值
groovy复制def name = 'World' "Hello $name" // 输出Hello World -
三引号字符串:保留格式的多行字符串
groovy复制def multiLine = ''' Line 1 Line 2 '''
字符串插值的高级用法:
groovy复制def user = [name:'Alice', age:25]
"Name: ${user.name}, Age: ${user.age}"
"计算表达式: ${1 + 2 * 3}"
2.3 集合类型
Groovy对集合进行了语法糖优化:
groovy复制// 列表
def list = [1, 2, 3] // ArrayList
list << 4 // 添加元素
println list[1] // 访问元素
// 映射
def map = [key1:'value1', key2:'value2']
map.key3 = 'value3' // 添加键值对
println map.key1 // 访问值
集合操作符:
groovy复制def nums = [1, 2, 3, 4]
nums.collect { it * 2 } // [2,4,6,8]
nums.findAll { it > 2 } // [3,4]
nums.inject(0) { sum, n -> sum + n } // 10 (求和)
3. 类型系统高级特性
3.1 动态类型与静态类型
Groovy独特之处在于它同时支持静态类型和动态类型:
groovy复制// 静态类型检查
@groovy.transform.TypeChecked
def staticTypedMethod() {
String str = "text"
str = 123 // 编译错误!
}
// 动态类型
def dynamicTypedMethod() {
def var = "text"
var = 123 // 允许
}
类型推断规则:
- 整数默认为Integer
- 小数默认为BigDecimal
- 大整数默认为Long或BigInteger
3.2 可选类型与类型转换
Groovy提供灵活的类型转换机制:
groovy复制// 字符串转数字
def num = '123' as Integer
num = '123'.toInteger()
// 列表转集合
def set = [1,2,3] as Set
// 自定义转换
class Money {
BigDecimal amount
String currency
static asType(Class target) {
if(target == String) {
return "$amount $currency"
}
}
}
def money = new Money(amount: 100, currency: 'USD')
String str = money as String // "100 USD"
3.3 空安全操作
Groovy提供多种方式处理null:
groovy复制// 安全导航操作符
def length = obj?.name?.length()
// Elvis操作符
def displayName = user.name ?: 'Anonymous'
// 空断言
def nonNull = value != null ? value : throw new AssertionError()
4. 最佳实践与常见问题
4.1 变量命名规范
推荐命名约定:
- 常规变量:camelCase
- 常量:UPPER_CASE
- 闭包参数:单个字母(it, e等)
groovy复制def userName = 'Alice'
final MAX_RETRY = 3
list.each { println it }
4.2 性能优化建议
- 循环内避免频繁创建对象
- 大量计算时考虑使用显式类型
- 谨慎使用元编程特性
groovy复制// 不好的写法
def sum = 0
(1..10000).each { sum += it }
// 更好的写法
int sum = 0
for(int i=1; i<=10000; i++) {
sum += i
}
4.3 常见问题排查
-
类型转换错误:
groovy复制try { def num = 'abc' as Integer } catch(NumberFormatException e) { println "转换失败: ${e.message}" } -
空指针异常:
groovy复制def result = possiblyNull?.operation() ?: defaultValue -
作用域混淆:
groovy复制def x = 1 void printX() { def x = 2 // 遮蔽了外部的x println x // 输出2 }
5. 实际应用案例
5.1 配置文件处理
groovy复制// 读取配置
def config = new ConfigSlurper().parse(new File('config.groovy').text)
// config.groovy内容示例:
/*
app {
name = 'MyApp'
port = 8080
features = ['logging', 'cache']
}
*/
println "应用名称: ${config.app.name}"
5.2 数据处理管道
groovy复制def processData(data) {
data.findAll { it.active } // 过滤
.collect { it.value * 1.1 } // 转换
.inject(0) { sum, v -> sum + v } // 聚合
}
def items = [
[active:true, value:100],
[active:false, value:200],
[active:true, value:50]
]
println "总和: ${processData(items)}" // 输出165.0
5.3 DSL实现
利用Groovy的变量特性可以轻松创建DSL:
groovy复制// 定义DSL
class DslBuilder {
def methodMissing(String name, args) {
println "调用方法: $name, 参数: $args"
}
def propertyMissing(String name) {
println "访问属性: $name"
this
}
}
// 使用DSL
def dsl = new DslBuilder()
dsl.order {
item 'Book'
quantity 2
price 19.99
}
