用 Map 实例化一个 @Immutable Groovy 对象?
Instantiate an @Immutable Groovy object with a Map?
Groovy 有一个简洁的语法,可以将 POGO 与地图结合起来,例如:
class Person {
Address address
}
class Address {
String city
}
Person p = new Person([address: [city: 'Toronto']])
assert p.address.city == 'Toronto'
即使是 深度嵌套 模型也行得通!我试过使用 @Immutable 模型这样做,但无济于事:
@groovy.transform.Immutable
class Person {
Address address
}
@groovy.transform.Immutable
class Address {
String city
}
//works:
Address a = new Address('Toronto')
Person p = new Person(a)
assert p.address.city == 'Toronto'
//not works:
Person p = new Person([address: [city: 'Toronto']])
// ==> java.lang.RuntimeException: @Immutable processor doesn't know how to handle field 'address' of type 'java.util.LinkedHashMap' while constructing class Person.
从 JSON -> 地图 -> POGO 这样做特别棒。
有什么想法吗?
单独的 @Immutable
注释不足以让 Groovy 知道它可以真正构造一个不可变对象,因为声明的属性本身可能是可变的。因此,所有属性必须是 "known" 才能在脚本为 运行.
时保持不变
现在,由于我不明白的原因,在同一个脚本中声明 属性 的 class 是不可变的是不够的。您必须使用 knownImmutableClasses
参数在 class 声明本身中声明 属性 是不可变的:
@groovy.transform.Immutable(knownImmutableClasses = [Address])
class Person {
Address address
}
或knownImmutables
参数:
@groovy.transform.Immutable(knownImmutables = ['address'])
class Person {
Address address
}
通过对 Person
class 声明的任一更改,您的脚本应该 运行 完全符合预期。
Groovy 有一个简洁的语法,可以将 POGO 与地图结合起来,例如:
class Person {
Address address
}
class Address {
String city
}
Person p = new Person([address: [city: 'Toronto']])
assert p.address.city == 'Toronto'
即使是 深度嵌套 模型也行得通!我试过使用 @Immutable 模型这样做,但无济于事:
@groovy.transform.Immutable
class Person {
Address address
}
@groovy.transform.Immutable
class Address {
String city
}
//works:
Address a = new Address('Toronto')
Person p = new Person(a)
assert p.address.city == 'Toronto'
//not works:
Person p = new Person([address: [city: 'Toronto']])
// ==> java.lang.RuntimeException: @Immutable processor doesn't know how to handle field 'address' of type 'java.util.LinkedHashMap' while constructing class Person.
从 JSON -> 地图 -> POGO 这样做特别棒。
有什么想法吗?
单独的 @Immutable
注释不足以让 Groovy 知道它可以真正构造一个不可变对象,因为声明的属性本身可能是可变的。因此,所有属性必须是 "known" 才能在脚本为 运行.
现在,由于我不明白的原因,在同一个脚本中声明 属性 的 class 是不可变的是不够的。您必须使用 knownImmutableClasses
参数在 class 声明本身中声明 属性 是不可变的:
@groovy.transform.Immutable(knownImmutableClasses = [Address])
class Person {
Address address
}
或knownImmutables
参数:
@groovy.transform.Immutable(knownImmutables = ['address'])
class Person {
Address address
}
通过对 Person
class 声明的任一更改,您的脚本应该 运行 完全符合预期。