Подтвердить что ты не робот

Разные между неизменяемыми и эффективно неизменяемыми объектами?

Это предложение из Java Concurrency in Practice

Общие объекты только для чтения включают неизменяемые и эффективно неизменяемые объекты.

Каковы различия между неизменяемыми и эффективно неизменяемыми объектами?

4b9b3361

Ответ 1

Экземпляры класса, который не является расширяемым и поля которого все final и сами неизменяемы, являются неизменяемыми.

Экземпляры класса, поля которого не могут быть мутированы из-за деталей его методов, являются фактически неизменными. Например:

final class C {
  final boolean canChange;
  private int x;
  C(boolean canChange) { this.canChange = canChange; }
  public void setX(int newX) {
    if (canChange) {
      this.x = newX;
    } else {
      throw new IllegalStateException();
    }
  }
}

Некоторые экземпляры C являются фактически неизменяемыми, а некоторые не являются.

Другим примером являются массивы нулевой длины. Они эффективно неизменяемы, хотя их содержащий класс не является непревзойденным, поскольку нет элемента из них, который можно изменить.


Joe-E использует верификатор, чтобы доказать, что некоторые классы допускают только неизменяемые экземпляры. Все, помеченные знаком Immutable, проверяются, и определенные классы, такие как String (эффективно неизменяемые, поскольку его char[] не исчезает), внушаемые в неизменном виде.

Joe-E: ориентированное на безопасность подмножество Java говорит

Неизменяемый интерфейс, определяемый библиотекой Joe-E, рассматривается особым языком: верификатор Joe-E проверяет, что каждый объект, реализующий этот интерфейс, будет быть (глубоко) неизменным и вызывает ошибку времени компиляции, если это не может быть автоматически проверено.

Ответ 2

Вот мое понимание от немного поиска и поиска этой статьи. Эффективно неизмеримый объект - это объект, который содержит поля, которые могут быть мутированы, но он не позволяет чему-либо мутировать эти поля, потому что он никогда не дает вам ссылки на них. Например, скажем, вы создаете в нем класс с ArrayList. ArrayList изменяемы, но если ваш класс всегда возвращает копию массива ArrayList, а все остальное в вашем классе является неизменным, то ваш класс становится практически неизменным: нет способа изменить состояние экземпляра вашего класса.

Сообщение в блоге дает это как пример эффективно неизменяемого класса:

import java.awt.*;

public class Line {

   private final Point start;
   private final Point end;

   public Line(final Point start, final Point end) {
       this.start = new Point(start);
       this.end = new Point(end);
   }

   public void draw() {
       //...
   }

   public Point getStart() {
       return new Point(start);
   }

   public Point getEnd() {
       return new Point(end);
   }
}

Point объекты изменяемы, но это нормально, потому что этот класс не дает никому прямой ссылки на его экземпляры Point. Вместо этого он возвращает новый экземпляр с тем же значением в нем. Таким образом, никто не может изменить состояние класса Line. Это делает класс Line эффективным.

Итак, как это отличается от действительно неизменяемого класса? У действительно неизменяемого класса есть поля, которые также неизменны. Предположим, что Line была действительно неизменной. Для этого нам также придется представить, что Point неизменна. Сделав эти предположения, метод getStart() мог бы быть написан следующим образом:

public Point getStart() {
   return start;
}

Ответ 3

Взгляните на этот ответ:

эффективно неизменна и неизменна. Разница между эффективно неизменными и неизменными заключается в том, что в первом случае вам все равно нужно публиковать объекты безопасным способом. Для действительно неизменяемых объектов, которые не нужны. Поэтому действительно неизменяемые объекты предпочтительнее, потому что их легче публиковать, причины, о которых я говорил выше, говорят, почему вы предпочитаете несинхронизированную публикацию.

fooobar.com/questions/234901/...

Ответ 4

Неизменяемые объекты полностью инкапсулируют свое внутреннее состояние, и они не позволяют изменять это состояние после построения (возможно, с использованием final и т.д.), поэтому они могут делиться между несколькими потоками, потому что чтение из общего объекта не является вредным для несколько потоков.

Эффективно неизменяемые объекты могут изменять свое состояние до совместного использования несколькими потоками, но после того, как они "опубликованы" (т.е. несколько ссылок передаются нескольким потокам), они защищают себя от модификации.

Неизменяемые объекты не позволяют использовать полезные методы разработки программного обеспечения, такие как ленивая инициализация, потому что для ленивого инициализации свойства или поля они должны быть изменчивыми, что нарушает беззаботное их свойство concurrency. Эффективно неизменяемые объекты ослабляют эти ограничения, чтобы получить лучшее из обоих миров, тщательно зная, когда они могут безопасно изменять свое внутреннее состояние и когда это запрещено.