2013-05-21 2 views
18

Это предложение от Java Параллелизм на практикеРазные между неизменяемыми и эффективно неизменяемыми объектами?

Shared только для чтения объекты включают в себя непреложные и эффективно неизменные объекты.

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

+0

См. [Эффективные объекты неизменяемости] (http://stackoverflow.com/questions/8707426/do-effectively-immutable-objects-make-sense), в котором также упоминается книга, к которой вы обращаетесь. – Bobulous

+0

См. Также [Должны ли все свойства неизменяемого объекта быть окончательными?] (Http://stackoverflow.com/questions/16061030/must-all-properties-of-an-immutable-object-be-final) – assylias

ответ

14

Экземпляры класса, который не является расширяемым, и чьи поля являются все 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: A Security-Oriented Subset of Java говорит

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

+0

«Экземпляры класса, поля которого не могут быть мутированы из-за деталей его методов, являются фактически неизменяемыми» - это неточно. _Effectively Immutable_ может быть любым объектом до тех пор, пока он не будет мутирован после того, как он будет опубликован _safley publushed_ (например, с помощью изменчивой ссылки или такой) –

+0

@OpDeCirkel, Суффикс -able на «неизменяемом» делает значение «неспособным к изменению» не просто " не мутировали ". Если у вас есть информация, указывающая на то, что простой смысл не тот, о котором говорил Goetz et al., Пожалуйста, добавьте ответ, и я продолжу. –

+0

JCP 3.5.4: Объекты, которые не являются технически неизменяемыми, но состояние которых * не будет изменено * после публикации, называются эффективно неизменными. - Это определение включает более широкий набор, а затем объекты, которые не имеют методов, которые мутируют их состояние. Просто наличие убеждения в том, что объект не должен быть мутирован после безопасной публикации, достаточно для того, чтобы быть эффективно неизменным. –

2

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

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

https://stackoverflow.com/a/7887675/1007546

6

Вот мое понимание с немного прибегая к помощи и найти this article. Эффективно неизмеримый объект - это объект, который содержит поля, которые могут быть мутированы, но он не позволяет чему-либо мутировать эти поля, потому что он никогда не дает вам ссылки на них. Например, скажем, вы создаете класс с ArrayList. ArrayList s изменяемы, но если ваш класс всегда возвращает копию массива 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 объектов изменчивы, но это нормально, потому что этот класс не дает никому прямую ссылку на это экземпляров Точечных , Вместо этого он возвращает новый экземпляр с тем же значением в нем. Таким образом, никто не может изменить состояние класса Line. Это делает класс Line эффектно неизменным.

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

public Point getStart() { 
    return start; 
} 
+0

@Gray см. мое редактирование, спасибо –

+0

Терминология меняется, но я считаю «эффективную неизменность» как характеристику объектов * экземпляров *, а не типов. Если нет пути выполнения, посредством которого ссылка на какой-либо конкретный экземпляр может быть подвержена коду, который может его изменить, этот экземпляр будет эффективно неизменен, даже если его класс не является. Я бы рассмотрел объект, который содержит только значения и ссылки на неизменяемые типы или эффективно-неизменяемые экземпляры и не подвергает никакому методу изменения собственной формы неизменным. – supercat

+0

@supercat от английского значения фразы, что имеет смысл. –

1

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

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

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

+0

Да String неизменен и не позволяет вам напрямую изменять его внутреннее состояние, но при вычислении хэш-кода он использует ленивый init. Так что технически String действительно непреложна. – chubbsondubs

Смежные вопросы