我想知道为什么最终修饰符不与getter和setter一起使用?
为什么这样做:
private int x;
public void setX(int x)
{
if(x >= 1) throw new IllegalArgumentException("X must be lower than 1");
this.x = x;
}
而不是:
private int x;
public final void setX(int x)
{
if(x >= 1) throw new IllegalArgumentException("X must be lower than 1");
this.x = x;
}
它没有改善封装?我一直试图用谷歌澄清它,但我没有运气。
先谢谢。
答案 0 :(得分:9)
你可能想要离开setter非final的一个原因是让子类进行自己的,更严格的参数检查:
public class Subclass extends Superclass {
public void setX(int x) {
if(x >= 0) throw new IllegalArgumentException("X must be negative");
super.setX(x);
}
}
当然这会中断Liskov Substitution Principle,因为子类会强化子类型中的前提条件。
答案 1 :(得分:1)
Java中最终方法的目的是它不能被子类覆盖或隐藏。因此,如果您需要为getter / setter提供该功能,那么将它们作为最终版本是完全正确的,否则没有任何目的。
答案 2 :(得分:0)
当可能存在另一种更强大的可能性时,我会严格避免使用setter:
如果您想改变字段,可能需要提供一个setter。
你提到的问题:
如果开发人员违反了我提供的验证规则,该怎么办? 覆盖setter ......我们应该使用final关键字吗?
我会说:“不要他这样做”。
确实,宣告制定者就像对世界说:
“你可以为我提供一些实地价值,然后你可以跟我做自己的事!” =>程序代码
“告诉!不要问”哲学会说:
“客户,告诉我该怎么做,我会做。”
一般而言,您的主要“复杂”逻辑将位于POJO的主要公共API中。
我怀疑开发人员是否会想要覆盖POJO的完整逻辑而不会冒完全不良行为的风险。
因此,例如,不是将打开的setter声明为任何值,而是强制将值传递给main方法,以便您可以控制流:
public void computeWith(int x) {
if(x <= 0) throw new IllegalArgumentException("X must be superior to 0");
//code computing here.
}
你会注意到,在这种做法中,POJO中甚至可能不再需要某些字段。
总结:很容易覆盖不良的验证规则......但行为风险很大。
只需2美分。
答案 3 :(得分:-1)
两种方式都存在争议,但如果你将方法设为最终(任何形式,不仅仅是getter或setter),那么另一个开发人员会诅咒你。很难预测你的课程将来会如何使用,并通过最终决定来限制它通常会让未来的开发人员变得更加困难。
例如,一些可怜的灵魂必须将您的代码与公司刚刚购买的新应用程序集成。星期五下午3点,演示将在周一早上到期。如果只有他们可以覆盖一个getter,他们可以强制它从新的应用程序返回一个包装的对象,事情会起作用。如果那个getter是最终的,他们必须开始改变,测试可能会释放你的代码,所以他们最终会在周末工作。
所以对未来的开发者有一些同情,除非你真的确定,否则不要让方法最终。即便如此,我也不会打扰。
专门用于非最终吸气剂的另一种用途是测试。它可以非常方便,特别是在使用不完美代码的集成测试期间,覆盖getter以注入类的测试实例。