Недостатки к неизменяемым объектам в Java?

Преимущества неизменяемых объектов в Java кажутся ясными:

  • согласованное состояние
  • автоматическая безопасность потока
  • Простота

Вы можете использовать неизменяемость, используя частные конечные поля и инъекцию конструктора.

Но каковы недостатки в пользу неизменяемых объектов в Java?

то есть.

  • несовместимость с инструментами ORM или веб-презентаций?
  • Негибкий дизайн?
  • Сложности реализации?

Возможно ли разработать крупномасштабную систему (граф глубоких объектов), которая преимущественно использует неизменяемые объекты?

Ответ 1

Но каковы недостатки благоприятствовать неизменяемым объектам в Java? несовместимость с ORM или веб-сайтом инструменты презентации?

Структуры, основанные на рефлексии, сложны неизменяемыми объектами, так как они требуют впрыска конструктора:

  • в Java нет аргументов по умолчанию, что заставляет нас ВСЕГДА предоставлять все необходимые зависимости
  • переопределение конструктора может быть беспорядочным
  • имена аргументов конструктора обычно не доступны через отражение, что заставляет нас зависеть от порядка аргументов для разрешения зависимостей

Сложности реализации?

Создание неизменяемых объектов по-прежнему является скучной задачей; компилятор должен позаботиться о деталях реализации, как в groovy

Возможно ли разработать крупномасштабную систему (граф глубоких объектов), которая преимущественно использует неизменяемые объекты?

определенно да; неизменные объекты делают большие строительные блоки для других объектов (они предпочитают композицию), так как гораздо легче поддерживать инвариант сложного объекта, когда вы можете положиться на его неизменные компоненты. Единственный недостаток для меня - создание многих временных объектов (например, String concat была проблемой в прошлом).

Ответ 2

С неизменностью, в любое время, когда вам нужно изменить данные, вам нужно создать новый объект. Это может быть дорого.

Представьте, что вам нужно изменить один бит в объекте, который потребляет несколько мегабайт памяти: вам нужно создать экземпляр целого нового объекта, выделить память и т.д. Если вам нужно делать это много раз, изменчивость становится очень привлекательной.

Ответ 3

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

Если вы действительно смотрите на программы, которые используют измененные объекты, вы обнаружите, что они подвержены "атаке", изменяя:

  • объекты, переданные конструкторам
  • объекты, переданные методам
  • объекты, возвращенные из методов.

Проблема не проявляется очень часто, потому что большинство программ не меняют данные (они на самом деле неизменяемы, поскольку они никогда не меняются).

Я лично делаю все возможное, чтобы закончить. У меня, вероятно, 90% -95% всех переменных (параметры, локальные, экземпляры, статические, исключения и т.д.), Отмеченные как окончательные. Есть некоторые случаи, когда он должен быть изменчивым, но в подавляющем большинстве случаев это не так.

Я думаю, это может зависеть от вашего внимания. Если вы пишете библиотеки для сторонних пользователей, вы думаете об этом гораздо больше, чем если вы пишете приложение, которое будет поддерживать только вас (или ваша команда).

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

Ответ 4

Ты очень много ответил на свой вопрос. Спецификация JavaBean, я не верю, упоминает о неизменности, но JavaBeans - это хлеб и масло многих фреймворков Java.

Ответ 5

В сущности, в реальном мире состояние, связанное со многими особыми идентичностями, изменится. Если я спрошу, что такое "нынешняя позиция Джо Бьюика", сегодня это может быть место в Сиэтле, а завтра это может быть место в Лос-Аламосе. Было бы возможно определить и создать объект GeographicLocation, значение которого всегда будет представлять местоположение, где Джо Бьюик был в определенный момент времени и никогда не изменится - если сегодня он представляет собой место в Сиэтле, тогда он всегда будет делать так. Однако такой объект не будет иметь постоянной идентичности как "нынешнее местоположение Джо Бьюика".

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

Невозможно, чтобы все объекты были неизменными. Если объект неизменен, то он не может иметь неизменяемого идентификатора, который инкапсулирует что-либо за пределы его текущего состояния. Однако, если объект изменчив, он может иметь неизменную идентичность, значение которой превосходит ее нынешнее состояние. Во многих ситуациях наличие неизменной идентичности более полезно, чем наличие неизменяемого состояния, и в таких ситуациях изменяемые объекты почти необходимы. Хотя в некоторых случаях можно "имитировать" изменяемые объекты, имея неизменный объект, который будет искать самую последнюю версию неизменяемых объектов для поиска информации, которая может "изменяться" между одной версией и следующей, такие подходы часто крайне неэффективен. Даже если бы каждый мог магически получать раз в минуту привязанную книгу, которая давала местонахождение каждого транспортного средства повсюду, поиск "Джо Бьюика" в книге займет гораздо больше времени, чем просто задание "настоящего местоположения Джо Бьюика", который всегда будет знать, где был автомобиль.

Ответ 6

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

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

Ответ 7

С неизменяемым объектом, если значение нужно изменить, оно должно быть заменено новым экземпляром. В зависимости от жизненного цикла объекта, заменяя его другим экземпляром, потенциально может увеличить время сбора мусора (длительное время). Это становится более важным, если объект хранится в памяти достаточно долго, чтобы быть помещенным в поколение.

Ответ 8

Проблема в java заключается в том, что нужно жить со всеми этими объектами, где класс выглядит следующим образом:

class Mutable {
    State1 f1;
    MoreState f2;
    void doSomething() {  // mutate the state, but don't document it }
    void doSomethingElse()  /// mutate the state heavily, do not mention in doc
}  

(Обратите внимание на отсутствующий интерфейс Cloneable).

Проблема с сборщиком мусора в настоящее время не такая большая. VM довольны короткими живыми объектами.

Достижения в технологии компилятора /JIT позволят, рано или поздно, оптимизировать создание промежуточных временных объектов. Например:

BigInteger  three =, two =, i1 = ...;
BigInteger  i2 = i1.mul(three).div(two);  

JIT может заметить, что промежуточный объект i1.mul(три) может использоваться для конечного результата и вызывать вариант метода div, который работает на изменяемом аккумуляторе.

Ответ 10

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

Что касается вашего графика, вы можете сделать его узлы неизменными и позволить другому классу заботиться о связях между ними, или вы можете сделать изменяемый node, который будет заботиться о своих собственных дочерних элементах и ​​имеет неизменяемый класс значений.

Ответ 11

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

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

Самая большая вещь, которую я когда-либо делал с ~ 90% неизменяемыми объектами, была интерпретатором игрушек-esque, поэтому, безусловно, возможно выполнить сложные Java-проекты.

Ответ 12

в неизменяемых данных вы не задаете два раза... см. haskell и scala vals (и clojure курса)...

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

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

с imuttable данными, вы не устанавливаете вещи более одного раза.. его совершенно новый способ программирования.. вы можете в конечном итоге использовать немного больше памяти.., но распараллеливание является естественным и безболезненным.

Ответ 13

Как и любой инструмент, вы должны знать, когда его использовать, а когда нет.

Как и в Tehblanx, если вы хотите изменить состояние переменной, которая содержит неизменяемый объект, вам нужно создать новый объект, который может быть дорогим, особенно если объект большой и сложный. Абсолютно верно, но это просто означает, что вам нужно разумно решить, какие объекты должны быть изменчивыми и которые должны быть неизменными. Если кто-то говорит, что ВСЕ объекты должны быть неизменными, ну, это просто сумасшедшие разговоры.

Я бы сказал, что объекты, которые представляют собой один логический "факт", должны быть неизменными, а объекты, которые представляют несколько фактов, должны быть изменчивыми. Например, Integer или String должны быть неизменными. Объект "Клиент", который содержит имя, адрес, текущую сумму, дату последней покупки и т.д., Должен быть изменен. Конечно, я могу сразу придумать сто исключений для такого общего правила. Исключением, которое я делаю все время, является то, что у меня есть класс, который существует только как оболочка, чтобы содержать примитив в некотором случае, когда примитив не является законным, как в коллекции, но мне нужно постоянно его обновлять.

Ответ 14

В Java метод не может возвращать несколько объектов, например return a, b, c. Возвращение массива объектов делает код выглядящим уродливым. В этой ситуации я должен передать изменяемые объекты методу и позволить ему изменять состояния этих объектов. Тем не менее, я не знаю, является ли возвращение нескольких объектов запахом кода или нет.

Ответ 15

Ответ - нет. Нет никаких веских причин быть изменчивыми.

Вы столкнулись с проблемами с большим количеством фреймворков (или версий фреймворка), для которых требуются изменяемые объекты, чтобы работать с ними (Spring Я смотрю в вашем направлении). По мере того, как вы будете работать с ними и пробираетесь через код, вы сотрясаете свой кулак в гневе, что вам нужно ввести грязную изменчивость в другой славный блок кода, когда его можно было бы легко избежать.

Я уверен, что есть ограниченные угловые случаи (возможно, более гипотетические, что-либо), где накладные расходы на создание и сбор объектов неприемлемы. Но я призываю людей, чтобы этот аргумент рассматривал такие языки, как scala, где включенные коллекции по умолчанию неизменяемы, а затем посмотрите на список приложений с критическими потребностями, построенных поверх этой концепции.

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

Ответ 16

Некоторые реализации неизменяемых объектов имеют транзакционные средства для обновления неизменяемого объекта. Подобно тому, как базы данных обеспечивают безопасные транзакции и откаты. Но в отличие от многих ответов здесь. Неизменяемые объекты никогда не меняются. Типичная операция.

B = append(A,C)

B - новый объект. Точно так же, как A и C. Никакой модификации не было сделано для A или C. Внутренне реализация красного черного дерева делает такую ​​семантику достаточно быстрой, чтобы ее можно было использовать.

Недостатком является то, что это не так быстро, как делать операции на месте. Но это только сравнивает одну часть системы. Оценивая возможные недостатки, мы должны смотреть на систему в целом. И у меня лично нет четкой картины всего воздействия. Хотя я подозреваю, что неизменность побеждает в конце.

Я знаю, что некоторые эксперты утверждают, что на верхнем уровне красно-черного дерева есть борьба. И это имеет отрицательный эффект в throught-put.

Ответ 17

Мое самое большое беспокойство в неизменных структурах данных - как сохранить/восстановить их. То есть, если класс имеет конечные поля, я не могу его создать, а затем установить его поля.