Как установить член объекта в неизменяемый в java? [Дубликат]

Кажется, что это редкий случай, но вот что со мной произошло:

Мы использовали @Inject вместо @Autowired, который является стандартом javaee, поддерживаемым Spring. В каждом месте он работал нормально, а бобы вводили правильно, а не в одно место. Инъекция компонента выглядит одинаково

@Inject
Calculator myCalculator

Наконец, мы обнаружили, что ошибка заключалась в том, что мы (фактически, функция автозавершения Eclipse) импортировали com.opensymphony.xwork2.Inject вместо javax.inject.Inject!

Итак, чтобы суммировать, убедитесь, что ваши аннотации (@Autowired, @Inject, @Service, ...) имеют правильные пакеты!

78
задан Joachim Sauer 10 June 2011 в 12:33
поделиться

13 ответов

  • Не предоставлять методы «setter» - методы, которые изменяют поля или объекты, на которые ссылаются поля.
  • Сделать все поля окончательными и частными.
  • Не выполнять позволить подклассам переопределять методы. Самый простой способ сделать это - объявить класс окончательным. Более сложный подход заключается в том, чтобы сделать конструктор частным и создавать экземпляры в заводских методах.
  • Если поля экземпляра включают ссылки на изменяемые объекты, не разрешайте эти объекты изменять: не предоставляйте методы, которые изменить изменяемые объекты. Не используйте ссылки на изменяемые объекты. Никогда не храните ссылки на внешние, изменяемые объекты, переданные конструктору; при необходимости, создавать копии и хранить ссылки на копии. Аналогичным образом создайте копии своих внутренних изменяемых объектов, когда это необходимо, чтобы избежать возврата оригиналов в ваши методы.
2
ответ дан Ajay 22 August 2018 в 21:13
поделиться

Классы не являются неизменяемыми, объекты есть.

Неизменяемые средства: мое публичное видимое состояние не может измениться после инициализации.

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

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

13
ответ дан Alexander Pogrebnyak 22 August 2018 в 21:13
поделиться
  • 1
    делая все поля статическими ограничениями для всех экземпляров для совместного использования того же состояния, которое не очень полезно. – aviad 12 June 2011 в 06:33

Просто не добавляйте к классу методы public mutator (setter).

12
ответ дан BalusC 22 August 2018 в 21:13
поделиться
  • 1
    как насчет всех статических членов? делает ссылку или состояние объекта для такого типа объектов? – Neel Salpe 10 June 2011 в 12:35
  • 2
    Не имеет значения. Если вы не можете изменить их извне каким-то способом, это непреложно. – BalusC 10 June 2011 в 12:36
  • 3
    на который нельзя ответить, поскольку мы не знаем, что делают статические члены ... из них они могут изменять частные поля. Если они делают это, то класс не является неизменным. – Angel O'Sphere 10 June 2011 в 12:36
  • 4
    И конструктор по умолчанию класса должен быть private, или класс должен быть final. Просто чтобы избежать наследования. Поскольку наследование нарушает инкапсуляцию. – Talha Ahmed Khan 10 June 2011 в 12:37

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

Преимущества объекта Immutable

Параллелизм и многопоточность Это автоматически Thread-safe, так что проблема синхронизации .... и т. Д.

Не нужно copy constructor Не нужно внедрять клон . Класс не может be override Сделать поле в качестве частных и окончательных участников принудительной сборки для полного создания объекта за один шаг, вместо использования конструктора no-Argument

Неизменяемые объекты - это просто объекты, состояние которых означает, что данные объекта не могут измениться после создания неизменяемого объекта.

см. Ниже код.

public final class ImmutableReminder{
    private final Date remindingDate;

    public ImmutableReminder (Date remindingDate) {
        if(remindingDate.getTime() < System.currentTimeMillis()){
            throw new IllegalArgumentException("Can not set reminder" +
                    " for past time: " + remindingDate);
        }
        this.remindingDate = new Date(remindingDate.getTime());
    }

    public Date getRemindingDate() {
        return (Date) remindingDate.clone();
    }
}
2
ответ дан brainless 22 August 2018 в 21:13
поделиться

На сайте oracle , как создать неизменяемые объекты в Java.

  1. Не предоставлять методы setter - методы, которые изменяют поля или объекты
  2. Сделать все поля окончательными и приватными.
  3. Не разрешать подклассам переопределять методы. Самый простой способ сделать это - объявить класс окончательным. Более сложный подход состоит в том, чтобы сделать конструктор частным и построить экземпляры в заводских методах.
  4. Если поля экземпляра включают ссылки на изменяемые объекты, не разрешайте эти объекты изменять: I. Не предоставлять методы, которые изменяют изменяемые объекты. II. Не используйте ссылки на изменяемые объекты. Никогда не храните ссылки на внешние, изменяемые объекты, переданные конструктору; при необходимости, создавать копии и хранить ссылки на копии. Аналогичным образом создайте копии своих внутренних изменяемых объектов, когда это необходимо, чтобы избежать возврата оригиналов в ваши методы.
3
ответ дан e11438 22 August 2018 в 21:13
поделиться

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

  1. Класс должен быть помечен как final
  2. Все поля должны быть приватными и final
  3. Заменить сеттеры конструктором (для присвоения значения переменной).

Давайте взглянем на то, что мы набрали выше:

//ImmutableClass
package younus.attari;

public final class ImmutableExample {

    private final String name;
    private final String address;

    public ImmutableExample(String name,String address){
        this.name=name;
        this.address=address;
    }


    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

}

//MainClass from where an ImmutableClass will be called
package younus.attari;

public class MainClass {

    public static void main(String[] args) {
        ImmutableExample example=new ImmutableExample("Muhammed", "Hyderabad");
        System.out.println(example.getName());

    }
}
1
ответ дан Hidde 22 August 2018 в 21:13
поделиться

Обычно игнорируемые, но важные свойства неизменяемых объектов

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

Рассмотрим следующие классы:

public final class ImmutableClass {

  private final MutableClass mc;

  public ImmutableClass(MutableClass mc) {
    this.mc = mc;
  }

  public MutableClass getMutClass() {
    return this.mc;
  }
}

public class MutableClass {

  private String name;

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }
}


public class MutabilityCheck {

public static void main(String[] args) {

  MutableClass mc = new MutableClass();

  mc.setName("Foo");

  ImmutableClass iMC = new ImmutableClass(mc);

  System.out.println(iMC.getMutClass().getName());

  mc.setName("Bar");

  System.out.println(iMC.getMutClass().getName());

  }

 }

Ниже приведен вывод из MutabilityCheck:

 Foo
 Bar

Важно отметить, что

  1. Построение изменяемых объектов на неизменяемом объекте (через конструктор) либо путем «копирования», либо «клонирования» в переменные экземпляра неизменяемого, описываемые следующими изменениями:
    public final class ImmutableClass {
    
       private final MutableClass mc;
    
       public ImmutableClass(MutableClass mc) {
         this.mc = new MutableClass(mc);
       }
    
       public MutableClass getMutClass() {
         return this.mc;
       }
    
     }
    
     public class MutableClass {
    
      private String name;
    
      public MutableClass() {
    
      }
      //copy constructor
      public MutableClass(MutableClass mc) {
        this.name = mc.getName();
      }
    
      public String getName() {
        return this.name;
      }
    
      public void setName(String name) {
       this.name = name;
      } 
     }
    

по-прежнему не гарантирует полную неизменность, поскольку из класса MutabilityCheck все еще действует следующее:

  iMC.getMutClass().setName("Blaa");
  1. Однако запуск MutabilityCheck с изменениями, внесенными в 1., приведет к на выходе:
    Foo
    Foo
    
  2. . Чтобы достичь полной неизменяемости объекта, все его зависимые объекты также должны быть неизменными
0
ответ дан KJ Sudarshan 22 August 2018 в 21:13
поделиться

Чтобы создать неизменяемый класс, вам необходимо выполнить следующие шаги:

Declare the class as final so it can’t be extended.
Make all fields private so that direct access is not allowed.
Don’t provide setter methods for variables
Make all mutable fields final so that it’s value can be assigned only once.
Initialize all the fields via a constructor performing deep copy.
Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.
3
ответ дан Mohit Singh 22 August 2018 в 21:13
поделиться

Ниже приведены жесткие требования к неизменяемому объекту.

  1. Сделать окончательный класс
  2. сделать все члены окончательными, установить их явно, в статическом блоке или в конструктор
  3. Сделать все члены private
  4. Нет Методы, которые изменяют состояние
  5. Будьте предельно осторожны, чтобы ограничить доступ к изменяемым элементам (помните, что поле может быть final но объект все еще может быть изменен, т. е. private final Date imStillMutable). Вы должны сделать defensive copies в этих случаях.

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

Чтобы увидеть проблему в действии, рассмотрите приведенный ниже пример:

public class MyApp{

    /**
     * @param args
     */
    public static void main(String[] args){

        System.out.println("Hello World!");

        OhNoMutable mutable = new OhNoMutable(1, 2);
        ImSoImmutable immutable = mutable;

        /*
         * Ahhhh Prints out 3 just like I always wanted
         * and I can rely on this super immutable class 
         * never changing. So its thread safe and perfect
         */
        System.out.println(immutable.add());

        /* Some sneak programmer changes a mutable field on the subclass */
        mutable.field3=4;

        /*
         * Ahhh let me just print my immutable 
         * reference again because I can trust it 
         * so much.
         * 
         */
        System.out.println(immutable.add());

        /* Why is this buggy piece of crap printing 7 and not 3
           It couldn't have changed its IMMUTABLE!!!! 
         */
    }

}

/* This class adheres to all the principles of 
*  good immutable classes. All the members are private final
*  the add() method doesn't modify any state. This class is 
*  just a thing of beauty. Its only missing one thing
*  I didn't declare the class final. Let the chaos ensue
*/ 
public class ImSoImmutable{
    private final int field1;
    private final int field2;

    public ImSoImmutable(int field1, int field2){
        this.field1 = field1;
        this.field2 = field2;
    }

    public int add(){
        return field1+field2;
    }
}

/*
This class is the problem. The problem is the 
overridden method add(). Because it uses a mutable 
member it means that I can't  guarantee that all instances
of ImSoImmutable are actually immutable.
*/ 
public class OhNoMutable extends ImSoImmutable{   

    public int field3 = 0;

    public OhNoMutable(int field1, int field2){
        super(field1, field2);          
    }

    public int add(){
       return super.add()+field3;  
    }

}

На практике очень часто встречается вышеупомянутая проблема в средах зависимости Injection. Вы явно не создаете экземпляры, а ссылка суперкласса, которую вы даете, может фактически быть подклассом.

Отказ в том, что для того, чтобы сделать твердые гарантии о неизменности, вы должны пометить класс как final. Это подробно описано в Эффективная Java Джошуа Блоха и явно указано в спецификации для модели памяти Java .

78
ответ дан nsfyn55 22 August 2018 в 21:13
поделиться
  • 1
    как насчет всех статических членов? – Neel Salpe 10 June 2011 в 12:34
  • 2
    для этого класса не обязательно быть окончательным. – Angel O'Sphere 10 June 2011 в 12:37
  • 3
    @Nilesh: неизменность является свойством экземпляров . Статические элементы обычно не относятся к какому-либо одному экземпляру, поэтому они не входят в картину здесь. – Joachim Sauer 10 June 2011 в 12:38
  • 4
    Пункт 15 статьи Джошуа Блоха о неизменяемости - Нет методов, которые изменяют состояние, Все поля окончательные, Все поля приватные, Убедитесь, что класс не может быть расширен, Обеспечьте эксклюзивный доступ к любым изменяемым компонентам. – nsfyn55 10 June 2011 в 13:01
  • 5
    @Jaochim. Они абсолютно являются частью уравнения. Возьмите пример выше, если я добавлю изменяемый статический член и использую его в функции добавления ImSoImmutable, у вас есть та же проблема. Если класс неизменен, то все аспекты должны быть неизменными. – nsfyn55 10 June 2011 в 13:31

Минимизировать изменчивость

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

JDK неизменяемые классы: String, классы в штучной упаковке (классы-оболочки), BigInteger и BigDecimal и т. Д. .

Как сделать класс неизменным?

  1. Не предоставлять какие-либо методы, которые изменяют состояние объекта (известные как мутаторы).
  2. Обеспечить что класс не может быть расширен.
  3. Сделать все поля окончательными.
  4. Сделать все поля закрытыми. Это не позволяет клиентам получить доступ к изменяемым объектам, на которые ссылаются поля, и напрямую изменять эти объекты.
  5. Сделать защитные копии. Обеспечьте эксклюзивный доступ к любым изменяемым компонентам. public list getList () {return Collections.unmodifiableList (список); & lt; === защитная копия изменяемого поля перед возвратом его вызывающему абоненту}

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

import java.util.Date;
public final class ImmutableClass {

       public ImmutableClass(int id, String name, Date doj) {
              this.id = id;
              this.name = name;
              this.doj = doj;
       }

       private final int id;
       private final String name;
       private final Date doj;

       public int getId() {
              return id;
       }
       public String getName() {
              return name;
       }

     /**
      * Date class is mutable so we need a little care here.
      * We should not return the reference of original instance variable.
      * Instead a new Date object, with content copied to it, should be returned.
      * */
       public Date getDoj() {
              return new Date(doj.getTime()); // For mutable fields
       }
}
import java.util.Date;
public class TestImmutable {
       public static void main(String[] args) {
              String name = "raj";
              int id = 1;
              Date doj = new Date();

              ImmutableClass class1 = new ImmutableClass(id, name, doj);
              ImmutableClass class2 = new ImmutableClass(id, name, doj);
      // every time will get a new reference for same object. Modification in              reference will not affect the immutability because it is temporary reference.
              Date date = class1.getDoj();
              date.setTime(date.getTime()+122435);
              System.out.println(class1.getDoj()==class2.getDoj());
       }
}

Для получения дополнительной информации см. Мой блог: http: //javaexplorer03.blogspot. в / 2015/07 / минимизации-mutability.html

2
ответ дан Pang 22 August 2018 в 21:13
поделиться
  • 1
    @Pang есть другой способ инициализировать поля, отличные от конструктора. У меня более 20 полей в моем классе. Очень сложно инициализировать все поля с помощью конструктора, некоторые поля также являются необязательными. – Nikhil Mishra 10 February 2018 в 18:57
  • 2
    @NikhilMishra, вы можете использовать шаблон проектирования Builder для инициализации переменных во время построения объекта. Вы можете сохранить обязательные переменные в конструкторе и остальные необязательные переменные, которые должны быть установлены с использованием методов setter. Но, строго говоря, вы не будете создавать класс True Immutable. – sunny_dev 8 March 2018 в 07:41

Неизменяемые объекты - это те объекты, состояние которых не может быть изменено после их создания, например, класс String является неизменяемым классом.

Особенности неизменяемых классов:

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

Ключи для записи неизменяемого класса:

  • убедитесь, что класс нельзя переопределить
  • сделать все переменные-члены private & amp; final
  • не дают своих методов настройки
  • ссылка на объект не должна просачиваться во время фазы строительства
1
ответ дан ralight 22 August 2018 в 21:13
поделиться

объект называется неизменяемым, если его состояние не может быть изменено после его создания. Один из самых простых способов создания неизменяемого класса в Java заключается в том, что все его поля являются окончательными. Если вам нужно написать неизменяемый класс, который включает в себя изменяемые классы, такие как «java.util.Date». Чтобы сохранить неизменность в таких случаях, советуется вернуть копию исходного объекта

1
ответ дан Rudra 22 August 2018 в 21:13
поделиться
  • 1
    Не рекомендуется возвращать копию, ее необходимо. Но также необходимо, чтобы в конструкторе была создана защитная копия. В противном случае объект может быть изменен за кулисами. – Ryan 7 August 2014 в 00:22

Чтобы сделать класс неизменным в Java, вы можете иметь в виду следующие моменты: 1. Не предоставлять методы setter для изменения значений любой из переменных экземпляра класса. 2. Объявите класс как 'final' . Это предотвратило бы распространение любого другого класса и, следовательно, исключение из него любого метода, который мог бы изменять значения переменных экземпляра. 3. Объявите переменные экземпляра как private и final . 4. Вы также можете объявить конструктор класса как private и добавить фабричный метод для создания экземпляра класса, когда это требуется.

Эти точки должны помочь !!

6
ответ дан VishEnthusiast 22 August 2018 в 21:13
поделиться
  • 1
    WRT # 4 Как видимость конструктора влияет на изменяемость? Строка неизменна, но имеет несколько общественных конструкторов. – Ryan 7 August 2014 в 00:19
  • 2
    Как сказал @Ryan, то же самое относится и к переменным экземпляра: почему они должны быть объявлены private? – MC Emperor 7 January 2016 в 08:53
Другие вопросы по тегам:

Похожие вопросы: