我想看看是否可以使用 Lombok 创建一个不可变的 Java 类。我在 Lombok 网站上找到了这个页面“不可变类变得非常简单”,但我不相信它:https://projectlombok.org/features/Value
我已经使用他们在该页面中使用的示例类对其进行了测试,即
@Value
public class ValueExample {
String name;
@With(AccessLevel.PACKAGE) @NonFinal int age;
double score;
protected String[] tags;
@ToString(includeFieldNames=true)
@Value(staticConstructor="of")
public static class Exercise<T> {
String name;
T value;
}
}
并写了一个小测试:
public static void main(String... args) {
String tags[] = {"a", "b", "c"};
ValueExample t = new ValueExample("name", 1, 2.3, tags);
System.out.println("BEFORE:" + Arrays.toString(t.getTags()));
String[] tagsToModify = t.getTags();
for (int i = 0; i < tags.length; i++) {
tagsToModify[i] = "?";
}
System.out.println("AFTER: " + Arrays.toString(t.getTags()));
}
测试的输出是:
BEFORE:[a, b, c]
AFTER: [?, ?, ?]
对我来说这意味着类不是一成不变的。 我错过了一些明显的东西吗?
问题是
tags
是一个 Array
,因此是一个引用类型,而数组是可变的。虽然您确实无法更改 tags
的值(例如,您无法将其重新分配以引用不同的数组),但它引用的数组可以由持有对它的引用的任何人(包括ValueExample
类本身,或您创建的用于测试此行为的 main
方法)。
暂时将反射放在一边(因为它提供了一个破坏不变性的“后门”),对于一个真正不可变的类,所有引用的属性也应该是不可变的 - 而 Array 不是 - 或者你可能不得不求助于防御性复制等技术