Setter params final в Java
Я всегда программировал на java, и недавно я начал изучать некоторые c++.
В C++ принято устанавливать параметры setter как const, почему мы не видим этого так много в java ?
Я имею в виду, есть ли какие-либо недостатки в создании сеттера, например:
public void setObject(final Object o){ this.o=o; }
vs
public void setObject(Object o){ this.o=o; }
первый должен принудительно для объекта param o оставаться постоянным через всю функцию набора, не так ли ?
Edit:
окончательный парам будет настаивать, чтобы этого не произошло:
public void setName(String name){
name="Carlos";
this.name=name;
}
пользователь никогда не сможет установить имя, отличное от"Carlos"
2 ответов
хорошо,final
параметр / переменная не могут быть назначены. Поскольку компилятор java должен быть способен определить, является ли переменная / параметр на самом деле final (для анонимных внутренних классов), оптимизация не является фактором AFAIK.
это больше, что C++ имеет больший набор инструментов, который java пытался уменьшить. Следовательно, используя C++ const string&
важно, говоря
- строка передается указателем, доступ осуществляется автоматически разыменованный.
- если фактический аргумент является переменной, сама переменная не изменяется.
- имейте в виду, что может быть оператор преобразования для передачи чего-то другого, чем
const string&
.
теперь java:
- Java не выделяет объекты в стеке, только сохраняет примитивные типы и дескрипторы объектов в стеке.
- Java не имеет выходных параметров: переменная, переданная вызову метода, никогда не изменит свой немедленный значение.
возвращаясь к вашему вопросу:
как сеттер в java в основном не выиграет от конечного параметра. Окончательным будет контракт, чтобы не использовать переменную для второго назначения.
:public final void setXyz(Xz xyz) {
this.xyz = xyz;
}
полезнее: этот метод не может быть переопределен, и, следовательно, может безопасно использоваться в конструкторе. (Вызов переопределенного метода в конструкторе будет происходить в контексте все еще не инициализированного дочернего экземпляра.)
мало преимуществ в установке параметра метода Java как окончательного, так как это не останавливает кого-то от изменения состояния ссылки на параметр в методе. Все, что он предотвращает, это повторное присвоение переменной параметра чему-то другому, что ничего не делает с исходной ссылкой, и позволяет использовать параметр в анонимных внутренних классах. Если вам нужна истинная безопасность в этой ситуации, вы попытаетесь сделать ваши типы параметров неизменяемыми, если вероятный.
редактировать
Вы писали:
public void setObject(Object o){
o++; // this does not compile
this.o=o;
}
который смешивает примитивный числовой и ссылочный тип. Это имеет смысл только в том случае, если o является целым числом или другим числовым классом-оболочкой, и даже если это так, его окончание не помешает кому-то создать:
private void setI(final Integer i) {
this.i = 1 + i;
}
но ни ваш код, ни этот код выше не повлияют на объект параметра на стороне вызывающего кода.
редактировать
ОК теперь вы писали:
public void setName(String name){
name="Carlos";
this.name=name;
}
но тогда кто-то мог бы написать
public void setName(final String name){
this.name= name + " Carlos";
}
вот где опасность приходит и где финал не помогает. Скажем, у вас есть класс под названием Name:
public class Name {
private String lastName;
private String firstName;
public Name(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
а затем класс, Foo, с полем имени и сеттером. Это опасно код:
class Foo {
private Name name;
public void setName(final Name name) {
name.setFirstName("Carlos");
this.name = name;
}
}
потому что он не только изменяет состояние поля, он изменяет состояние ссылки на имя в вызывающем коде и финал модификатор не поможет ни на йоту. Решение: сделать имя неизменяемым.
например,
import java.util.Date;
// class should be declared final
public final class BetterName {
private String lastName;
private String firstName;
private Date dateOfBirth;
public BetterName(String lastName, String firstName, Date dob) {
this.lastName = lastName;
this.firstName = firstName;
// make and store a private copy of non-immutable reference types
dateOfBirth = new Date(dob.getTime());
}
// only getters -- no setters
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public Date getDateOfBirth() {
// return copies of non-immutable fields
return new Date(dateOfBirth.getTime());
}
}