如果对象的状态在构造后无法更改,则认为该对象是不可变的。由于它们无法更改状态,因此它们不会被线程干扰破坏或在不一致的状态下观察到,从而使它们在并发应用程序中很有用。
例如,Java中的String对象是不可变的。
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ImmutableTest {
@Test
public void testImmutableObjs() {
String firstName = "yogen";
String lastName = "rai";
// concatenate two strings
String fullName = firstName.concat(" ").concat(lastName);
assertEquals("yogen", firstName);
assertEquals("rai", lastName);
assertEquals("yogen rai", fullName);
}
}
“”(空白)上的firstName和lastName的串联将不会修改它们中的任何一个,而是创建一个将由fullName引用的新对象。
定义自定义不可变对象 以下规则定义了创建不可变对象的简单策略:
如果实例字段包含对可变对象的引用,则不允许更改这些对象:
使用日期对象定义自定义不可变对象
java.util
。*
中的Date对象不是线程不可变的。
好消息是,JDK 8之后的新java.time。* API将 Date 对象作为不可变对象。例如,在下面的示例中,即使属性dateJoined 是 Date object ,Student对象也是不可变的 。
import java.time.LocalDate;
final class Student {
private final String name;
private final int age;
private final LocalDate dateJoined;
public Student(String name, int age, LocalDate dateJoined) {
this.name = name;
this.age = age;
this.dateJoined = dateJoined;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public LocalDate getDateJoined() {
return dateJoined;
}
}
public class TestImmutable {
@Test
public void testImmutableObject() {
Student original = new Student("Yogen", 23, LocalDate.of(2016, 5, 1));
LocalDate modifiedLocalDate = original.getDateJoined().plusYears(2);
Student expected = new Student("Yogen", 23, LocalDate.of(2016, 5, 1));
assertEquals(expected, original);
}
}
上面示例的代码在GitHub上可用。
不变对象的好处
* 不可变对象无副作用,因此更易于构造,测试和使用。
* 它们更容易缓存,因为对对象的修改不会影响其原始状态。
* 真正不可变的对象始终是线程安全的
* 避免身份可变性问题
* 它们有助于避免时间耦合
原文链接:https://codingdict.com/