Setter在Java中完成了最后的决赛

时间:2015-06-28 18:35:22

标签: java const final setter

我一直用java编程,最近我开始学习一些c ++。

在C ++中,将setter params设置为const是常规的,为什么我们不能在java中看到这一点?

我的意思是创建像这样的setter有任何缺点:

}

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

cell.backgroundColor = [UIColor whiteColor];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[self.tableView setRowHeight:45];
cell.textLabel.text = [self.alertSubArray objectAtIndex:indexPath.row];
cell.textLabel.textAlignment = NSTextAlignmentLeft;

return cell;

}

VS

public void setObject(final Object o){ this.o=o; }

第一个应该强制Object param o在整个set函数中保持不变,而不是?

编辑:

最终的参数将强制执行此操作:

public void setObject(Object o){ this.o=o; }

用户将永远无法设置与" Carlos"

不同的名称

2 个答案:

答案 0 :(得分:7)

将Java方法参数设置为final是没有什么好处的,因为它不会阻止某人更改方法中的参数引用状态。它所阻止的只是将参数变量重新赋值给其他东西,这对原始引用没有任何作用,它允许在匿名内部类中使用该参数。如果您希望在这种情况下保持真正的安全性,那么您应尽可能使参数类型不可变。

修改
你发布了:

["blah.clah##something_else"]

其中混合了原始数字和引用类型。只有o是Integer或其他数字包装类才有意义,即使如此,最终也不会阻止某人创建:

public void setObject(Object o){ 
     o++; // this does not compile
     this.o=o; 
}

但是你的代码和上面的代码都不会影响调用代码端的参数对象。

修改
好的,现在你发布了:

private void setI(final Integer i) {
   this.i = 1 + i;
}

但是有人可以写

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

这就是危险来临的地方,也是最终无济于事的地方。假设您有一个名为Name的类:

public void setName(final String name){ 
     this.name= name + " Carlos"; 
}

然后是一个类,Foo,带有Name字段和setter。这是危险代码:

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;
   }
}

因为它不仅会更改字段的状态,还会更改调用代码中Name引用的状态,而 final 修饰符将无助于一位。解决方案:使名称不可变。

例如,

class Foo {
   private Name name;

   public void setName(final Name name) {
      name.setFirstName("Carlos");
      this.name = name;
   }
}

答案 1 :(得分:5)

好的,无法分配final参数/变量。由于java编译器需要能够确定变量/参数是否实际 final(对于匿名内部类),优化不是AFAIK的因素。

C ++有更大的工具集,java试图减少它。因此,使用C ++ const string&很重要,说

  1. 字符串由指针传递,访问权限自动解除引用。
  2. 如果实际参数是变量,则变量本身不会更改。
  3. 请注意,可能存在转换运算符,用于传递除const string&以外的其他内容。
  4. 现在java:

    1. Java不在堆栈上分配对象,只保留堆栈上的原始类型和对象句柄。
    2. Java没有输出参数:传递给方法调用的变量永远不会改变其立即值。
    3. 回到你的问题:

      由于java中的setter大多数不会受益于最终参数。 决赛将是不将该变量用于第二次作业的合同。

      然而:

      public final void setXyz(Xz xyz) {
          this.xyz = xyz;
      }
      

      更有用:此方法无法覆盖,因此可以安全地在构造函数中使用。 (在构造函数中调用override方法将位于仍未初始化的子实例的上下文中。)