Setter 最终参数 Java
Setter params final in Java
我一直在java编程,最近我开始学习一些c++。
在 C++ 中,通常将 setter 参数设置为常量,为什么我们在 java 中看不到这一点?
我的意思是像这样创建 setter 有什么缺点吗:
public void setObject(final Object o){ this.o=o; }
对
public void setObject(Object o){ this.o=o; }
第一个应该强制对象参数 o 在整个 set 函数中保持不变,而不是?
编辑:
最后一个参数将强制这不会发生:
public void setName(String name){
name="Carlos";
this.name=name;
}
用户将永远无法设置不同于 "Carlos"
的名称
将 Java 方法参数设置为 final 没有什么好处,因为它不会阻止某人在方法中更改参数引用的状态。它所阻止的只是将参数变量重新分配给其他东西,这对原始引用没有任何作用,并且它允许在匿名内部 classes 中使用参数。如果你想在这种情况下真正安全,你会尽可能使你的参数类型不可变。
编辑
您已发布:
public void setObject(Object o){
o++; // this does not compile
this.o=o;
}
它混合了原始数字和引用类型。仅当 o 是整数或其他数字包装器 class 时才有意义,即便如此,将其设为 final 也不会阻止某人创建:
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";
}
这就是危险所在,而 final 也无济于事。假设您有一个名为 Name:
的 class
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;
}
}
然后是 class,Foo,带有名称字段和 setter。这是危险代码:
class Foo {
private Name name;
public void setName(final Name name) {
name.setFirstName("Carlos");
this.name = name;
}
}
因为它不仅会改变字段的状态,还会改变调用代码中 Name 引用的状态,final 修饰符一点用都没有.解决方案:使 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());
}
}
好的,一个final
parameter/variable不能分配给。由于 java 编译器需要能够确定 variable/parameter 是否 实际上 最终(对于匿名内部 类),优化不是因素 AFAIK .
更多的是 C++ 拥有更大的工具集,java 试图减少。因此使用 C++ const string&
很重要,说
- 字符串通过指针传递,访问自动解除引用。
- 如果实参是一个变量,变量本身不会改变。
- 请注意,可能有一个转换运算符用于传递
const string&
以外的其他内容。
现在java:
- Java不在栈上分配对象,只在栈上保留原始类型和对象句柄。
- Java 没有输出参数:传递给方法调用的变量永远不会改变它的立即值。
回到你的问题:
作为 java 中的 setter 大多数情况下不会从最终参数中获益。
final 将是不使用该变量进行第二次赋值的合同。
但是:
public final void setXyz(Xz xyz) {
this.xyz = xyz;
}
更有用:此方法不能被重写,因此可以在构造函数中安全使用。 (在构造函数中调用覆盖方法将在仍未初始化的子实例的上下文中。)
我一直在java编程,最近我开始学习一些c++。
在 C++ 中,通常将 setter 参数设置为常量,为什么我们在 java 中看不到这一点?
我的意思是像这样创建 setter 有什么缺点吗:
public void setObject(final Object o){ this.o=o; }
对
public void setObject(Object o){ this.o=o; }
第一个应该强制对象参数 o 在整个 set 函数中保持不变,而不是?
编辑:
最后一个参数将强制这不会发生:
public void setName(String name){
name="Carlos";
this.name=name;
}
用户将永远无法设置不同于 "Carlos"
的名称将 Java 方法参数设置为 final 没有什么好处,因为它不会阻止某人在方法中更改参数引用的状态。它所阻止的只是将参数变量重新分配给其他东西,这对原始引用没有任何作用,并且它允许在匿名内部 classes 中使用参数。如果你想在这种情况下真正安全,你会尽可能使你的参数类型不可变。
编辑
您已发布:
public void setObject(Object o){
o++; // this does not compile
this.o=o;
}
它混合了原始数字和引用类型。仅当 o 是整数或其他数字包装器 class 时才有意义,即便如此,将其设为 final 也不会阻止某人创建:
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";
}
这就是危险所在,而 final 也无济于事。假设您有一个名为 Name:
的 classpublic 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;
}
}
然后是 class,Foo,带有名称字段和 setter。这是危险代码:
class Foo {
private Name name;
public void setName(final Name name) {
name.setFirstName("Carlos");
this.name = name;
}
}
因为它不仅会改变字段的状态,还会改变调用代码中 Name 引用的状态,final 修饰符一点用都没有.解决方案:使 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());
}
}
好的,一个final
parameter/variable不能分配给。由于 java 编译器需要能够确定 variable/parameter 是否 实际上 最终(对于匿名内部 类),优化不是因素 AFAIK .
更多的是 C++ 拥有更大的工具集,java 试图减少。因此使用 C++ const string&
很重要,说
- 字符串通过指针传递,访问自动解除引用。
- 如果实参是一个变量,变量本身不会改变。
- 请注意,可能有一个转换运算符用于传递
const string&
以外的其他内容。
现在java:
- Java不在栈上分配对象,只在栈上保留原始类型和对象句柄。
- Java 没有输出参数:传递给方法调用的变量永远不会改变它的立即值。
回到你的问题:
作为 java 中的 setter 大多数情况下不会从最终参数中获益。 final 将是不使用该变量进行第二次赋值的合同。
但是:
public final void setXyz(Xz xyz) {
this.xyz = xyz;
}
更有用:此方法不能被重写,因此可以在构造函数中安全使用。 (在构造函数中调用覆盖方法将在仍未初始化的子实例的上下文中。)