哪种设置字段值更好,为什么?

时间:2015-06-13 00:35:05

标签: java optimization constructor

这个问题可能很愚蠢,但我只是想知道,有什么不同吗?

class A{
    // common code
    private int field;
    public void setField(int field){
         this.field = field;
    }

    //way 1
    public A(int field){
        this.field = field;
    }

    //way 2
    public A(int field){
        setField(field);
    }
}

3 个答案:

答案 0 :(得分:4)

我怀疑没有“更好”的方式,只是想在当时适合你的目的。

我很喜欢 Way#1 。这是因为我尝试尽可能地将代码设为Encapsulated。在某种程度上,它也可以被认为是编程Java的Functional方式,因为您正在减少副作用。有时一起消除它们。

class A{
// common code
private int field;
public void setField(int field){
     this.field = field;
}

//way 1
public A(int field){
    this.field = field;
}
}

可以改写为......

class A{
// common code
private final int field;

//way 1
public A(int field){
    this.field = field;
}

是的,如果您需要在实例化后更改 field 的值,它将无效。也可以是 field 另一个对象或集合。

但是为了使课程尽可能不可变,可以标记为私有最终的字段也是如此。

当然,你不能用setter方法做到这一点。

答案 1 :(得分:2)

方式2更好,因为它为您提供了设置变量值的统一方法。但它带来了风险,因为你在构造函数中调用了一个可重写的方法。所以正确的语法是使用final关键字:

public final void setField(int field){
     this.field = field;
}

//way 2
public A(int field){
    setField(field);
}

使用final时,不会覆盖该方法。如果您无法承担最终方法,请不要在构造函数中调用setter。但是覆盖一个setter通常很奇怪。

这很好,因为您可能希望稍后更改设置器:

  • 添加参数检查并在需要时抛出IllegalArgumentException
  • 添加一个计数器
  • 通知观察者(以Observable模式)
  • 使其成为同步块以提供线程安全性
  • ...

你必须在一个地方做到这一点。这是DRY principle.

的实现
public final synchronized void setField(int field){
    if (0 <= field && field <= MAX_VALUE) {
        this.field = field;
    } else {
        throw new IllegalArgumentException();
    }   
}

//still has all the benefits of setter
public A(int field){
    setField(field);
}

A = new A(-1) //throws IllegalArgumentException

不要担心额外方法调用的优化和费用。 JVM通常可以通过内联方法来优化这些代码。

真正让开发变得更慢的是搜索错误。此方法可帮助您减少错误并更轻松地维护代码。

答案 2 :(得分:0)

嗯,对我而言,一方面是更多Java。我的意思是,我们应该知道构造函数应该做什么(在初始化时设置实例属性)以及setter应该做什么(提供一个公开的开放点来在你想要的时候更改实例属性)。

我们不应该在构造函数中放置任何逻辑

只是我的选择。