1. 简介

本文将介绍在 Groovy 中判断数据类型的几种常用方式。

需要注意的是,不同场景下的处理方式略有差异:

  • ✅ 基本类型(Primitives)的类型判断
  • ✅ 集合类型(Collections)的特殊处理
  • ✅ 对象与类变量的类型获取

掌握这些技巧,能帮你少踩不少坑,尤其是在动态类型和静态类型混用的 Groovy 项目中。

2. 基本类型

Groovy 支持与 Java 相同的原始数据类型。对于基本类型,我们有三种方式来判断其数据类型:

2.1 使用 instanceof 操作符

这是最直观的方式,用于判断某个变量是否为指定类型:

@Test
public void givenWhenParameterTypeIsInteger_thenReturnTrue() {
    Person personObj = new Person(10)
    Assert.assertTrue(personObj.ageAsInt instanceof Integer);
}

instanceof 是 Java 和 Groovy 共有的二元操作符,返回布尔值。
⚠️ 注意:Groovy 3 引入了 !instanceof 操作符,用于判断“不是某个类型”,使用时注意版本兼容性。

2.2 调用 getClass() 方法

通过对象的 getClass() 方法获取其运行时类:

def "givenWhenParameterTypeIsDouble_thenReturnTrue"() {
    given:
    Person personObj = new Person(10.0)

    expect:
    personObj.ageAsDouble.class == Double
}

2.3 使用 .class 操作符

Groovy 中可以直接对变量使用 .class 获取类型:

def "givenWhenParameterTypeIsString_thenReturnTrue"() {
    given:
    Person personObj = new Person("10 years")

    expect:
    personObj.ageAsString.class == String
}

✅ 三种方式均可用于基本类型,推荐优先使用 getClass(),更安全、语义清晰。

3. 集合类型

Groovy 对集合(List、Map 等)提供了原生支持,但类型判断时需格外小心,尤其是 .class 的使用。

3.1 List 类型判断

List 在 Groovy 中默认是 ArrayList,可以通过 .classgetClass() 获取类型:

def "givenGroovyList_WhenFindClassName_thenReturnTrue"() {
    given:
    def ageList = ['ageAsString', 'ageAsDouble', 10]

    expect:
    ageList.class == ArrayList
    ageList.getClass() == ArrayList
}

✅ 这里 .classgetClass() 效果一致,都能正确返回 ArrayList

3.2 Map 类型的坑 ❌

⚠️ 对 Map 使用 .class 会出问题!看下面例子:

@Test
public void givenGrooyMap_WhenFindClassName_thenReturnTrue() {
    def ageMap = [ageAsString: '10 years', ageAsDouble: 10.0]
    Assert.assertFalse(ageMap.class == LinkedHashMap)
}

❌ 为什么失败?
因为 ageMap.class 并不会返回 Map 的类类型,而是尝试从 Map 中获取 key 为 "class" 的值!
Groovy 会把 .class 当作 Map 的 key 来查找,而不是调用类方法。

✅ 正确做法:对 Map 必须使用 getClass()

assert ageMap.getClass() == LinkedHashMap

💡 小结:

  • List:.classgetClass() 都行
  • Map:**必须用 getClass()**,.class 会踩坑!

4. 对象与类变量

除了变量实例,我们有时还需要在反射层面获取类字段的类型信息。

4.1 获取类字段的类型

假设我们有如下 Person 类:

class Person {
    int ageAsInt
    double ageAsDouble
    String ageAsString
}

我们可以通过反射获取字段的类型:

def "givenClassName_WhenParameterIsInteger_thenReturnTrue"() {
    expect:
    Person.class.getDeclaredField('ageAsInt').type == int.class
}

getDeclaredField() 获取指定字段,.type 返回其 Class 类型。
这在元编程或构建通用工具时非常有用。

4.2 判断对象类型

对于对象实例,依然可以使用前面提到的方式:

def "givenWhenObjectIsInstanceOfType_thenReturnTrue"() {
    given:
    Person personObj = new Person()

    expect:
    personObj.class == Person
}

4.3 使用 in 操作符判断继承关系

Groovy 提供了 in 操作符,可用于判断类型归属,尤其适合判断子类:

def "givenWhenInstanceIsOfSubtype_thenReturnTrue"() {
    given:
    Student studentObj = new Student()

    expect:
    studentObj.class.superclass == Person
}

✅ 虽然 in 更常用于集合遍历,但在类型判断中结合 classsuperclass 也能派上用场。

5. 总结

本文系统梳理了 Groovy 中判断数据类型的几种方式:

方式 适用场景 推荐度 注意事项
instanceof 类型判断 支持 !instanceof(Groovy 3+)
getClass() 任意对象,最安全 ✅✅✅ 推荐优先使用,尤其对 Map
.class 基本类型、List 不要用于 Map
getDeclaredField().type 反射获取字段类型 适用于元编程场景
in + class 类型归属判断 结合继承关系使用

✅ 最佳实践建议:

  • 统一使用 getClass(),避免 .class 在 Map 上的陷阱
  • 反射场景用 .type 获取字段类型
  • 多态判断结合 instanceofsuperclass

所有示例代码已托管至 GitHub:https://github.com/baeldung/core-groovy-modules/core-groovy-2


原始标题:How to Determine the Data Type in Groovy