2015-07-03 4 views
2

Я делал некоторое чтение here для создания неизменяемых объектов, и мне было интересно, у меня есть следующий класс:Использование конечных частных или частных установщиков для неизменяемых классов

final public class AnonymousCilent { 

    final private String anonymousCilentID; 

    public AnonymousCilent(String anonymousCilentID) { 
     this.anonymousCilentID = anonymousCilentID; 
    } 

Это путь Oracle предлагает создать неизменны классы, однако, на C# вы можете объявить свой сеттер частным, в Java он остается неизменным, если я это сделаю?

private String anonymousCilentID; 

public AnonymousCilent(String anonymousCilentID) { 
    this.setAnonymousCilentID(anonymousCilentID); 
} 

public String getAnonymousCilentID() { 
    return anonymousCilentID; 
} 

private void setAnonymousCilentID(String anonymousCilentID) { 
    this.anonymousCilentID = anonymousCilentID; 
} 

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

+2

Почему у вас есть сеттер, если его никто не может назвать? –

+2

Почему у вас есть сеттер, если только этот класс может его назвать? – Makoto

+1

http://stackoverflow.com/questions/279507/what-is-meant-by-immutable – yfklon

ответ

3

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

Вы также можете вернуть клон вашего идентификатора пользователя в методе getAnonymousClientID.

Все объекты по умолчанию изменяются в Java.

EDIT: Так что все вы могли бы сделать, это вернуть свой идентификатор пользователя в методе GET, как это:

public String getUserID() { 
    return (String) userID.clone(); 
} 
+0

Итак, правильная практика использует закрытую конечную переменную, чтобы никто не вызывал ее по-настоящему, правильно? –

+0

Да. Или просто убедитесь, что переменная реализует Cloneable и возвращает копию запрашивающего кода с вызовом object.clone() – andrewdleach

+0

Поскольку 'anonymousCilentID' является строкой, клонирование не требуется. –

0

Частный сеттер совершенно бессмысленно. Любой код, который может вызвать частный сеттер, также может напрямую записываться в переменную. Это означает, что нет никакой гарантии, только потому, что вы сделали setter private, этот код не изменяет переменную.

+0

Спасибо, очень ценится. –

1

Создание поля final делает две вещи:

  • Требует значение, которое можно сделать с помощью конструктора (или по крайней мере быть решен во время строительства)
  • Запрещает создание сеттер для поле

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

0

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

0

Используйте поле final.

Ввод final на поле говорит любому разработчику, читающему ваш код, что класс неизменен - ​​это хорошо.

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

private String anonymousCilentID; 

public AnonymousCilent(String anonymousCilentID) { 
    this.setAnonymousCilentID(anonymousCilentID); 
} 

public String getAnonymousCilentID() { 
    return anonymousCilentID; 
} 

private void setAnonymousCilentID(String anonymousCilentID) { 
    this.anonymousCilentID = anonymousCilentID; 
} 

// This method seems reasonable, but it isn't OK  
public void clear() { 
    anonymousCilentID = null;   // <--- opps! 
} 

Это плохо.

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