使一个类不可变
创建不可变对象,创建后不能更改。 这使得不可变对象在并发和函数编程中非常有用。 要将Java类定义为不可变,我们必须将所有属性定义为readonly和private。 只有构造函数可以设置属性的值。 Groovy文档 具有适用于不可变对象的规则的完整列表。 使类不可变的Java代码很冗长,特别是因为需要重写hashCode()
,equals()
和toString()
方法。
Groovy有@ Immutable
转换为我们完成所有工作。 我们只需要在类定义中定义@Imputable
,我们为这个类创建的任何对象都是一个不可变对象。 Groovy按照不可变对象的规则生成一个类文件。 所以所有属性都是readonly,构造函数是为了设置属性,生成hashCode()
,equals()
和toString()
方法的实现,和 more。
@Immutable class User {
String username, email
Date created = new Date()
Collection roles
}
def first = new User(username: 'mrhaki', email: 'email@host.com', roles: ['admin', 'user'])
assert 'mrhaki' == first.username
assert 'email@host.com' == first.email
assert ['admin', 'user'] == first.roles
assert new Date().after(first.created)
try {
// Properties are readonly.
first.username = 'new username'
} catch (ReadOnlyPropertyException e) {
assert 'Cannot set readonly property: username for class: User' == e.message
}
try {
// Collections are wrapped in immutable wrapper classes, so we cannot
// change the contents of the collection.
first.roles << 'new role'
} catch (UnsupportedOperationException e) {
assert true
}
def date = new Date(109, 8, 16)
def second = new User('user', 'test@host.com', date, ['user'])
assert 'user' == second.username
assert 'test@host.com' == second.email
assert ['user'] == second.roles
assert '2009/08/16' == second.created.format('yyyy/MM/dd')
assert date == second.created
assert !date.is(second.created) // Date, Clonables and arrays are deep copied.
// toString() implementation is created.
assert 'User(user, test@host.com, Wed Sep 16 00:00:00 UTC 2009, [user])' == second.toString()
def third = new User(username: 'user', email: 'test@host.com', created: date, roles: ['user'])
// equals() method is also generated by the annotation and is based on the
// property values.
assert third == second