我正在为关键字final做准备。它用于定义无法在其子类中重写的方法。
但我有一个问题,就是找一些真正好的简单现实世界的例子,我想避免在子类中重写一个方法。
任何提示?
答案 0 :(得分:2)
final 方法有时可以由编译器内联到子类中,从而获得较小的性能优势。
至于何时希望避免子类提供自己的方法定义的示例,只要方法的定义对于对象的持久性或系统的性能至关重要,它就应该是最终的。
应该仔细考虑从构造函数调用的方法,通常它们必须是最终的,以确保强大的类定义。
真实世界的例子总是多开发者环境。如果你为一家处理信用卡信息的公司工作,并且你有一个做重要事情的java类,你不希望一些实习生意外覆盖一个重要的方法,所以你建立系统的方式甚至其他开发人员也不能它不安全。
也不要忘记最后的课程和最后的字段!
答案 1 :(得分:2)
作为一个人为的例子:您可能希望您的类通知观察对象某些状态发生了变化。您希望人们对您的类进行子类化,以便能够覆盖此状态的更改方式,但不会发送这些事件。
public class Womble {
public String fluff;
// notify listeners that the value of 'fluff' is changing
private void onFluffChanging() {
//…
}
// Others can override this method
protected void setFluffImpl(String value) {
fluff = value;
}
// But not this one, so the notification always gets sent
public final void setFluff(String value) {
onFluffChanging();
setFluffImpl(value);
}
}
一般情况下,当你想确保你的类的某些行为不会被子类“删除”时,你会使用final。有些人还喜欢默认使用final作为一切,以防止任何形式的意外使用他们的代码 - 唯一没有最终的类和方法是他们明确打算进行子类化的。后者在制作将被大量重用的代码时非常有用,特别是在制作将通过继承其类重复使用的代码时。
答案 2 :(得分:2)
要在这里平衡其他答案 - 确定的好答案 - 请记住,在实际使用中,通常很难准确预测将来如何使用课程。将final
添加到您的代码中是因为您觉得某些内容不应该更改,这可能会增加使用该代码的人未来的挫败感,并且final
总是可以被绕过创意开发人员以这种或那种方式。这只是一个问题,你想要多少诱惑他/她这样做。如果涉及到这一点,那么你最好希望那个人真的知道他或她在做什么。
答案 3 :(得分:2)
几乎所有使用Template Method模式的框架和库代码都有例子。
例如,在SwingWorker中,包括execute()
和run()
在内的许多方法都是最终的,但这些方法调用的方法doInBackground()
是抽象的,并且打算由子类,而其他方法有默认实现,但不是最终的,所以允许重写。
答案 4 :(得分:2)
非抽象类的equals()
方法的实现必须用final修饰符标记。这个陈述可以通过示例(标准库中的实际代码)轻松证明:
public class Date {
private transient long fastTime;
....
public long getTime() {
return getTimeImpl();
}
....
public boolean equals(Object obj) {
return obj instanceof Date && getTime() == ((Date) obj).getTime();
}
}
public class Timestamp extends java.util.Date {
public boolean equals(java.lang.Object ts) {
if (ts instanceof Timestamp) {
return this.equals((Timestamp)ts);
} else {
return false;
}
}
public boolean equals(Timestamp ts) {
if (super.equals(ts)) {
if (nanos == ts.nanos) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
这意味着违反了equals()合同:
date.equals(timestamp) == true
但
timestamp.equals(date) == false