如果对象的状态在构造后无法更改,则认为该对象是不可变的。由于它们无法更改状态,因此它们不会被线程干扰破坏或在不一致的状态下观察到,从而使它们在并发应用程序中很有用。
例如,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对象不是线程不可变的。
java.util
*
好消息是,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/