Если вы рассматриваете класс как составную часть или иерархию других классов и примитивов (целые числа, массивы и т. Д. c.), Неглубокая неизменяемость относится к неизменяемости (неизменности) только первого уровня.
Это контрастирует с термином «глубокая неизменность», который относится к неизменности всей иерархии. Большинство ощутимых преимуществ, которые вы слышите о неизменности, таких как неявная потокобезопасность, применимы только к чему-то глубоко неизменяемому.
Рассмотрим этот класс . Его нельзя изменить напрямую, но можно изменить косвенно, например
foo.getBar().setSomeProperty(5);
, поэтому он не является полностью неизменяемым.
Другой пример неглубокой неизменяемости, использующей только примитивы
class Foo {
private final int[] ints;
Foo(int[] ints) {
this.ints = ints;
}
}
Это может быть изменено следующим образом
int[] ints = {1};
Foo foo = new Foo(ints);
ints[0] = 2;
Для небольшой иерархии иногда просто сделать неглубоко неизменяемый класс глубоко неизменяемый. Обычно это включает в себя защитные копии или переключение изменяемых классов на неизменяемые варианты.
class Foo {
private final int[] ints;
Foo(int[] ints) {
// copy to protect against the kind of mutation shown above
this.ints = Arrays.copyOf(ints, ints.length);
}
// if you must have a getter for an array, make sure not to return the array itself,
// otherwise the caller can change it.
// for performance reasons, consider an immutable List instead - no copy required
int[] getInts() {
return Arrays.copyOf(ints, ints.length);
}
}