【问题标题】:Most appropriate place for bounds checking - constructor or setter?最适合边界检查的地方 - 构造函数或设置器?
【发布时间】:2012-09-13 15:59:50
【问题描述】:

对于 Java 来说还是比较新的,我想知道哪种方法更好地处理这个问题。我有一个带有一些参数的类构造函数,并且在这个类中还有公共 getter 和 setter:

private String name;
private Float value;

public MySampleClass(String theName, Float theValue) {
    setName(theName);
    setValue(theValue);
}

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

public value setValue(Float v) {
    this.value = v;
}

我想对这个 Float 做一些边界检查。似乎最好的放置位置是在 setter 中:

public value setValue(Float v) {
    if (v < 0.0f) {
        this.value = 0.0f;
    } else if (v > 1.0f) {
        this.value = 1.0f;
    }
}

这段代码最初在构造函数中进行边界检查,然后在 setter 中再次检查,这似乎是多余的。我更改了构造函数以调用 setter 并将检查放在那里。这更有意义吗?还是我违反了一些我完全不知道的约定?

【问题讨论】:

  • 在我看来你做得对。 (A) setter 的要点是提供验证以“保护”您的类的属性。
  • 显然是在 setter 中,因为它已在此处公开,因此在创建对象后可能会更改值。
  • 实际上没有正确的方法,我不喜欢你的方法,我会让setter只是设置值,并在setter之外执行绑定检查,因为它可能是将来会令人困惑,或者至少将其分离在类中的私有函数中,例如私有值 valueBoundsChecking(val){(logic....)return x} 然后, setValue(value v){this.value=valueBoundsChecking (v);},或类似的东西
  • 我只想指出,在发布的示例中,在构造函数和设置器中都进行了验证。验证代码本身不在构造函数本身内,但在运行 new MySampleClass() 时仍会运行验证 - 这是一个与问题可能被解释为略有不同的问题。您在这里所做的只是代码的智能重用。

标签: java coding-style constructor getter-setter


【解决方案1】:

从构造函数调用可覆盖的方法是个坏主意。做更多这样的事情:

private String name;
private Float value;

public MySampleClass(String theName, Float theValue) {
    this.name = theName;
    setValueImpl(theValue);
}

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

public void setValue(Float v) {
    setValueImpl(v);
}

private void setValueImpl(Float v) {
    if (v < 0.0f) {
        this.value = 0.0f;
    } else if (v > 1.0f) {
        this.value = 1.0f;
    }
}

这为您提供了两个地方的验证,并消除了对可覆盖方法的调用。有关更多信息,请参阅this question

编辑:如果您计划继承 MySampleClass 并希望验证设置器可用,请将其声明为 protected final 而不是 private

【讨论】:

  • +1 表示“从构造函数调用可覆盖的方法是个坏主意”
  • 好点,我没有考虑过覆盖方法的可能性。另外,我计划消除对 setName 的不必要的内部调用。
【解决方案2】:

对于相当简单的数据检查,例如您的示例,那么是的,在 setter 中进行验证是最有意义的。但是,如果theValue 的验证也依赖于theName(或其他东西),那么在构造函数(或构造函数调用的私有方法)中执行验证可能是值得的。

【讨论】:

  • 如果没有真正需要,最好还是避免在内部调用 setter(例如为 theName 调用 setter)。
猜你喜欢
  • 2022-01-13
  • 2013-10-21
  • 1970-01-01
  • 2021-12-05
  • 2016-06-02
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多