不可变类(Immutable Class)是指一旦实例化后,内部状态(字段值)无法被修改的类。其核心原则围绕“状态隔离”“防止修改”展开,具体包括:
private确保外部无法直接访问字段,final保证字段仅在构造函数中初始化,后续不可修改;setName()),仅通过构造函数或工厂方法初始化状态;List、Date),需在构造函数中进行深拷贝(如new ArrayList<>(inputList)),并在getter中返回不可变视图(如Collections.unmodifiableList()),避免外部代码通过引用修改内部状态;public final class ImmutablePerson {
private final String name; // 私有final字段
private final int age;
private final List<String> hobbies;
public ImmutablePerson(String name, int age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = new ArrayList<>(hobbies); // 防御性拷贝(保护可变对象)
}
// 只读getter(不提供setter)
public String getName() { return name; }
public int getAge() { return age; }
public List<String> getHobbies() {
return Collections.unmodifiableList(hobbies); // 返回不可变视图
}
}
关键点说明:
final类防止继承;private final字段确保封装性;hobbies进行深拷贝,避免外部传入的List被修改;getHobbies()返回unmodifiableList,防止外部通过返回的List修改内部状态。若类包含可变对象(如Date、数组),必须通过深拷贝隔离外部修改:
public final class ImmutableEvent {
private final Date eventTime;
private final String[] attendees;
public ImmutableEvent(Date eventTime, String[] attendees) {
this.eventTime = new Date(eventTime.getTime()); // 深拷贝Date
this.attendees = Arrays.copyOf(attendees, attendees.length); // 深拷贝数组
}
public Date getEventTime() { return new Date(eventTime.getTime()); } // 返回副本
public String[] getAttendees() { return Arrays.copyOf(attendees, attendees.length); } // 返回副本
}
注意:即使Arrays.copyOf创建了新数组,若数组元素是可变对象(如自定义类),仍需对元素进行深拷贝。
对于字段较多的不可变类,可使用建造者模式(Builder Pattern)提高可读性和灵活性:
public final class ImmutableProduct {
private final String name;
private final double price;
private final List<String> features;
private ImmutableProduct(Builder builder) {
this.name = builder.name;
this.price = builder.price;
this.features = new ArrayList<>(builder.features);
}
public static class Builder {
private String name;
private double price;
private List<String> features = new ArrayList<>();
public Builder name(String name) { this.name = name; return this; }
public Builder price(double price) { this.price = price; return this; }
public Builder addFeature(String feature) { this.features.add(feature); return this; }
public ImmutableProduct build() {
return new ImmutableProduct(this);
}
}
// Getter方法省略
}
// 使用示例
ImmutableProduct product = new ImmutableProduct.Builder()
.name("Laptop")
.price(999.99)
.addFeature("SSD")
.addFeature("Touchscreen")
.build();
优势:避免构造函数参数过多的问题,支持链式调用,同时保持不可变性。
对于高频使用的不可变对象(如配置项、枚举值),可通过缓存减少重复创建的开销:
public final class ImmutableConfig {
private static final Map<String, ImmutableConfig> CACHE = new HashMap<>();
private final String configKey;
private final int timeout;
private ImmutableConfig(String configKey, int timeout) {
this.configKey = configKey;
this.timeout = timeout;
}
public static ImmutableConfig getInstance(String configKey, int timeout) {
return CACHE.computeIfAbsent(configKey + timeout,
k -> new ImmutableConfig(configKey, timeout));
}
// Getter方法省略
}
注意:缓存需考虑线程安全(如使用ConcurrentHashMap)和内存泄漏问题(如及时清理无用缓存)。
setAccessible(true)修改private字段,可通过SecurityManager限制反射操作,但无法完全避免;StringBuilder);equals()和hashCode():不可变类的equals()需基于字段值比较,hashCode()需保证“相等的对象哈希值相等”(如使用Objects.hash(name, age)),确保对象在集合(如HashSet、HashMap)中正常工作。免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。