25. 能否创建一个包含可变对象的不可变对象
25. 能否创建一个包含可变对象的不可变对象
当然可以,比如 final Person[] persons = new Persion[]{} . persons 是不可变对象的引用,但其数组中的Person实例却是可变的.这种情况下需要特别谨慎,不要共享可变对象的引用.这种情况下,如果数据需要变化时,就返回原对象的一个拷贝。
在 Java 中,可以创建一个包含可变对象的不可变对象,但必须通过防御性设计来确保该对象的不可变性。虽然对象本身不能被修改,但如果其内部引用了可变对象,必须防止这些可变对象的状态被外部修改。
- 构造函数中进行防御性拷贝(Deep Copy)
- 在构造函数中对传入的可变对象进行深拷贝,以确保外部修改不会影响到内部状态。例如:
public final class ImmutableWrapper {private final List<String> internalList;public ImmutableWrapper(List<String> list) {this.internalList = new ArrayList<>(list); // 防御性拷贝}
}
- 返回只读视图(Unmodifiable View)
- 提供访问内部可变对象的方法时,返回只读视图,防止外部通过接口修改对象状态。例如:
public List<String> getList() {return Collections.unmodifiableList(internalList);
}
以下是一个完整的示例,展示如何创建一个包含可变对象的不可变类:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public final class ImmutableWrapper {private final List<String> internalList;public ImmutableWrapper(List<String> list) {this.internalList = new ArrayList<>(list); // 防御性拷贝}public List<String> getList() {return Collections.unmodifiableList(internalList); // 返回只读视图}public static void main(String[] args) {List<String> mutableList = new ArrayList<>();mutableList.add("Item1");ImmutableWrapper wrapper = new ImmutableWrapper(mutableList);// 外部修改不会影响内部列表mutableList.add("Item2");System.out.println(wrapper.getList()); // 输出: [Item1]// 尝试通过 wrapper 接口修改内部列表try {wrapper.getList().add("Item3"); // 抛出 UnsupportedOperationException} catch (UnsupportedOperationException e) {System.out.println("修改失败: " + e.getMessage());}}
}