1. Groovy变量基础入门
作为一门运行在JVM平台上的动态语言,Groovy的变量系统既保留了Java的静态特性,又提供了脚本语言的灵活性。与Java不同,Groovy中声明变量时类型是可选的,这种设计让代码更简洁,同时也带来了独特的类型推导机制。
1.1 变量声明方式
Groovy支持三种变量声明语法,每种都有其适用场景:
groovy复制// 强类型声明(Java风格)
String explicitType = "静态类型检查时推荐"
// 使用def关键字(动态类型)
def dynamicVar = "运行时确定类型"
// 直接赋值(脚本风格)
implicitVar = "适用于简单脚本"
经验提示:在Groovy 2.0+版本中,对于需要静态编译的代码(使用@CompileStatic注解),建议使用显式类型声明以获得更好的性能。而在普通脚本中,def关键字能提供更好的灵活性。
类型推导是Groovy的一大特色。当使用def或直接赋值时,Groovy会根据右侧的赋值内容自动判断变量类型:
groovy复制def example = 42 // 推导为Integer
example = "现在变成字符串" // 动态语言特性,允许改变类型
1.2 变量作用域
Groovy的作用域规则与Java类似但更灵活:
- 局部变量:在方法或代码块内声明,仅在该范围内有效
- 实例变量:在类中声明,属于对象实例
- 类变量:用static修饰,属于类本身
- 脚本变量:在脚本顶层声明的变量默认具有脚本作用域
特殊的是,在Groovy脚本中,未使用def声明的变量会自动提升为脚本作用域:
groovy复制x = 10 // 脚本作用域
def method() {
y = 20 // 危险!这也会提升为脚本作用域而非局部变量
def z = 30 // 正确的局部变量声明方式
}
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Groovy基本数据类型详解
Groovy全面支持Java的八种基本数据类型,同时通过自动装箱机制和扩展方法增强了它们的易用性。
2.1 数值类型处理
Groovy对数值类型的处理比Java更智能:
| 类型 | 示例 | 特殊支持 |
|---|---|---|
| int | 42 | 支持任意进制(0x, 0b等) |
| long | 100L | 大数自动提升为Long |
| BigDecimal | 3.1415926535 | 默认小数类型,避免精度问题 |
| BigInteger | 1234567890G | 支持超大整数运算 |
groovy复制def binary = 0b1101 // 二进制数
def hex = 0x1F // 十六进制
def big = 12345678901234567890 // 自动识别为BigInteger
避坑指南:当处理金融计算时,务必使用BigDecimal。Groovy中3.14默认是BigDecimal,但通过某些方式(如从Java方法返回)可能得到Double,这时应该显式转换:new BigDecimal('3.14')
2.2 字符串增强
Groovy字符串有三种形式,各具特色:
-
普通字符串(单引号)
groovy复制def simple = '单引号不支持插值' -
GString(双引号,支持插值)
groovy复制def name = 'Groovy' def greeting = "Hello ${name}" // 插值表达式 -
多行字符串(三重引号)
groovy复制def multiLine = ''' 第一行 第二行 ''' def templated = """ User: ${System.getProperty('user.name')} Date: ${new Date()} """
字符串操作扩展方法:
groovy复制// 字符串乘法
def repeat = 'a' * 3 // 'aaa'
// 安全导航
def length = str?.size() // 避免NPE
// 正则表达式简化
def matched = '123' ==~ /\d+/ // 返回true
2.3 集合类型语法糖
Groovy为集合操作提供了大量语法糖:
groovy复制// 列表定义
def nums = [1, 2, 3] // ArrayList
def linked = [4, 5, 6] as LinkedList // 指定类型
// 映射定义
def map = [name: 'Groovy', version: '4.0'] // LinkedHashMap
// 范围表达式
def range = 1..10 // 包含10
def exclusive = 1..<10 // 不包含10
集合操作扩展:
groovy复制// 查找第一个偶数
def even = nums.find { it % 2 == 0 }
// 收集转换
def squared = nums.collect { it * it }
// 展开操作符
def combined = [*nums, *range]
3. 类型系统进阶
3.1 动态与静态类型结合
Groovy独特之处在于支持三种类型检查模式:
-
动态类型(默认)
groovy复制def var = '字符串' // 运行时确定类型 var = 42 // 可以重新赋值为不同类型 -
静态类型检查(@TypeChecked)
groovy复制@TypeChecked void method() { String str = '类型安全' // str = 100 // 编译错误 } -
静态编译(@CompileStatic)
groovy复制@CompileStatic int add(int a, int b) { return a + b // 生成字节码与Java类似 }
3.2 可选类型与类型推断
Groovy的类型推断规则:
-
字面量赋值:根据字面量形式推断
groovy复制def intVal = 123 // Integer def decVal = 1.23 // BigDecimal -
方法返回值:根据return表达式推断
groovy复制def guessType() { Math.random() > 0.5 ? '字符串' : 42 } -
集合类型:自动推断元素类型
groovy复制def list = [1, 2, 3] // List<Integer>
性能提示:在热点代码路径上,显式类型声明可以帮助Groovy编译器生成更优化的字节码。
4. 特殊数据类型处理
4.1 闭包作为特殊变量
Groovy中闭包是一等公民,可以像变量一样传递:
groovy复制// 闭包赋值
def greet = { name -> "Hello, $name!" }
// 作为参数传递
3.times { print greet('Groovy') }
// 闭包类型推断
Closure<String> toUpper = { String s -> s.toUpperCase() }
4.2 原生JSON处理
Groovy内置了JSON支持:
groovy复制import groovy.json.*
def json = '''
{
"name": "Groovy",
"versions": ["1.8","2.5","3.0","4.0"]
}
'''
// 解析JSON
def obj = new JsonSlurper().parseText(json)
// 生成JSON
def output = new JsonBuilder()
output.person {
name 'Alice'
age 30
}
4.3 空值安全处理
Groovy提供了多种空值安全操作:
groovy复制// 安全导航操作符
def length = obj?.name?.length()
// Elvis操作符
def displayName = user.name ?: 'Anonymous'
// 安全下标访问
def firstVersion = obj.versions?[0]
5. 性能优化与最佳实践
5.1 类型选择策略
- 性能敏感场景:使用基本类型(int, long等)
- 数值计算:明确使用BigDecimal/BigInteger
- 集合操作:根据需求选择具体实现类
groovy复制def smallList = new ArrayList(10) // 预设大小 def freqMap = new HashMap(100) // 大容量Map
5.2 编译时类型检查
静态编译可以显著提升性能:
groovy复制@CompileStatic
class Calculator {
int add(int a, int b) { a + b }
}
5.3 避免常见陷阱
-
字符串比较:
groovy复制assert '42' == 42 // true,Groovy会自动转换 assert '42'.equals(42) // false,严格相等 -
浮点数精度:
groovy复制def precise = 0.1 + 0.2 // 使用BigDecimal -
集合修改:
groovy复制def unmodifiable = [1, 2, 3].asImmutable()
Groovy的变量系统设计充分体现了"约定优于配置"的理念。通过合理运用类型推导、动态特性和静态检查的组合,开发者可以在灵活性和性能之间取得平衡。对于从Java转来的开发者,建议逐步适应def的使用,而在性能关键路径上保持类型明确性
