什么时候使用java的@Override注释,为什么?

使用Java的@Override注释的最佳实践是什么?为什么?

@Override注释标记每一个被重写的方法似乎是多余的。是否有某些编程情况需要使用@Override,而其他情况不应该使用@Override?

943362 次浏览

我每次都用。它提供了更多的信息,当我在一年后重新访问代码时,我可以快速弄清楚发生了什么,而我已经忘记了我第一次想的是什么。

我总是使用标签。它是一个简单的编译时标志,用于捕捉我可能犯的小错误。

它将捕获诸如tostring()而不是toString()之类的东西

小事情有助于大项目。

每当一个方法覆盖了另一个方法,或者一个方法在接口中实现了签名。

@Override注释向你保证你确实重写了一些东西。如果没有注释,可能会出现拼写错误或参数类型和数字不同的情况。

它允许你(好吧,编译器)在你重写的方法名上使用了错误的拼写。

每次重写一个方法时使用它有两个好处。这样你就可以利用编译器检查来确保你实际上覆盖了一个方法。这样,如果您犯了拼写错误方法名或没有正确匹配参数的常见错误,您将得到警告,您的方法实际上并没有像您认为的那样重写。其次,它使您的代码更容易理解,因为当方法被覆盖时更明显。

此外,在Java 1.6中,您可以使用它来标记方法何时实现接口,以获得同样的好处。我认为最好有一个单独的注释(如@Implements),但这总比没有强。

使用@Override注释可以在编译时防止常见的编程错误。它会抛出一个编译错误,如果你在一个方法上有注释,而你实际上没有重写超类方法。

最常见的情况是,当您更改基类中的一个方法以拥有一个不同的参数列表时,这是有用的。子类中用于覆盖超类方法的方法将不再这样做,因为方法签名已更改。这有时会导致奇怪和意外的行为,特别是在处理复杂的继承结构时。@Override注释防止了这种情况。

如果您发现自己经常重写(非抽象)方法,您可能需要检查一下您的设计。当编译器无法捕捉错误时,它非常有用。例如,尝试在ThreadLocal中覆盖initValue(),这是我已经做过的。

在实现接口方法(1.6+特性)时使用@Override对我来说似乎有点过度。如果你有大量的方法,有些重写了,有些没有,这可能又是糟糕的设计(如果你不知道,你的编辑器可能会显示哪个是哪个)。

最佳实践是始终使用它(或让IDE为您填充它们)

@Override有用性是检测父类中没有向下报告的更改。 如果没有@Override,你可以改变一个方法签名而忘记改变它的覆盖,使用@Override,编译器会为你捕捉它

有这样的安全网总是好的。

我认为它在编译时提醒大家,该方法的目的是重写父方法。举个例子:

protected boolean displaySensitiveInformation() {
return false;
}

您将经常看到类似上述方法的内容,它覆盖基类中的方法。这是该类的一个重要实现细节——我们不希望显示敏感信息。

假设这个方法在父类中被更改为

protected boolean displaySensitiveInformation(Context context) {
return true;
}

此更改不会导致任何编译时错误或警告-但它完全改变了子类的预期行为。

回答您的问题:如果在超类中缺少具有相同签名的方法,则表明存在错误,则应该使用@Override注释。

@Override在接口上实际上是有帮助的,因为如果你改变了接口,你会得到警告。

我到处都用。 关于标记方法的工作,我让Eclipse为我做这件事,所以不需要额外的工作

我对持续重构非常虔诚....所以,我会利用每一件小事让它进行得更顺利。

最好将它用于打算重写的每个方法,以及Java 6+,用于打算作为接口实现的每个方法。

首先,它会在编译时捕获像“hashcode()”而不是“hashCode()”这样的拼写错误。当真正的原因是您的代码从未被调用时,调试为什么您的方法的结果似乎与您的代码不匹配可能会令人困惑。

同样,如果一个超类改变了一个方法签名,旧签名的重写就会被“孤立”,留下令人困惑的死代码。@Override注释将帮助您识别这些孤儿,以便可以修改它们以匹配新的签名。

这里有很多好的答案,所以让我提供另一种看待它的方式……

编码时没有多余的东西。输入@override不需要花费任何成本,但是如果您拼写错了方法名或签名稍有错误,节省的成本可能是巨大的。

可以这样想:在你浏览这里并输入这篇文章的时间里,你所花费的时间比你余生输入@override的时间还要多;但是它防止的一个错误可以节省你的时间。

Java尽其所能确保您在编辑/编译时不会犯任何错误,这是一种几乎免费的方法来解决整个类型的错误,这些错误在全面测试之外的任何其他方法都无法预防。

你能在Java中提出一种更好的机制来确保当用户想要重写一个方法时,他实际上做到了吗?

另一个巧妙的效果是,如果您不提供注释,它将在编译时警告您不小心覆盖了父方法——如果您不打算这样做,这可能会很重要。

它所做的另一件事是,当读取代码时,它会更明显地改变父类的行为。这有助于调试。

此外,在Joshua Block的著作《Effective Java》(第二版)中,第36项详细介绍了注释的好处。

接口实现上的@Override是不一致的,因为在java中没有“覆盖接口”这样的事情。

@Override在接口实现上是无用的,因为在实践中它不会捕获编译无论如何都不会捕获的错误。 只有一个牵强附会的场景,在实现上重写实际上是有作用的:如果你实现了一个接口,并且接口移除了方法,你将在编译时收到通知,你应该删除未使用的实现。注意,如果新版本的接口有new或CHANGED方法,你显然会得到一个编译错误,因为你没有实现新的东西

在1.6中不应该允许接口实现@Override,而不幸的是,eclipse选择自动插入注释作为默认行为,我们得到了大量杂乱的源文件。在阅读1.6代码时,您无法从@Override注释中看出一个方法实际上覆盖了超类中的一个方法,还是仅仅实现了一个接口。

在重写超类中的方法时使用@Override是可以的。

为了从编译器检查中获益,你应该总是使用Override注释。但是不要忘记Java Compiler 1.5在覆盖接口方法时不允许这个注释。您只能使用它来重写类方法(抽象与否)。

有些ide(如Eclipse)甚至配置了Java 1.6运行时或更高版本,它们保持与Java 1.5的一致性,并且不允许像上面描述的那样使用@override。要避免这种行为,您必须转到:项目属性->Java编译器->勾选“启用项目特定设置”->选择“编译器遵从级别”= 6.0或更高。

我喜欢在每次独立重写方法时使用这个注释,如果基是一个接口或类。

这可以帮助您避免一些典型的错误,例如当您认为您正在重写事件处理程序时,然后您没有看到发生任何事情。假设你想给某个UI组件添加一个事件监听器:

someUIComponent.addMouseListener(new MouseAdapter(){
public void mouseEntered() {
...do something...
}
});

上面的代码编译并运行,但是如果你在someUIComponent内移动鼠标,“do something”代码将提示运行,因为实际上你没有覆盖基本方法mouseEntered(MouseEvent ev)。你只需要创建一个新的无参数方法mouseEntered()。如果你使用了@Override注释,你就看到了一个编译错误,而且你没有浪费时间思考为什么你的事件处理程序没有运行。

  • 仅用于方法声明。
  • 带注释的方法 声明覆盖声明 李在超类型。< / >

如果持续使用,它可以保护您免受大量恶意漏洞的侵害。

使用@Override注释来避免这些错误: (在以下代码中发现错误:)

public class Bigram {
private final char first;
private final char second;
public Bigram(char first, char second) {
this.first  = first;
this.second = second;
}
public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
public int hashCode() {
return 31 * first + second;
}


public static void main(String[] args) {
Set<Bigram> s = new HashSet<Bigram>();
for (int i = 0; i < 10; i++)
for (char ch = 'a'; ch <= 'z'; ch++)
s.add(new Bigram(ch, ch));
System.out.println(s.size());
}
}

来源:有效的Java

这方面的智慧似乎正在改变。今天我安装了IntelliJ IDEA 9,并注意到它的“缺失@覆盖检查”现在不仅捕获实现的抽象方法,而且还捕获实现的接口方法。在我雇主的代码库和我自己的项目中,我一直习惯只对前者使用@Override——实现的抽象方法。但是,重新考虑这个习惯,在这两种情况下使用注释的优点就变得很明显了。尽管比较冗长,但它确实可以防止脆弱基类问题(不像c++相关的例子那样严重),其中接口方法名称发生变化,将可能实现的方法孤立在派生类中。

当然,这种情况多半是夸张的;派生类将不再编译,现在缺乏重命名接口方法的实现,今天可能会使用重命名方法重构操作来处理整个代码基。

鉴于IDEA的检查无法配置为忽略已实现的接口方法,今天我将改变我的习惯和我的团队的代码审查标准。

很简单——当你想重写父类中出现的方法时,使用@Override注释来进行正确的重写。如果你没有正确地覆盖它,编译器会警告你。

在实现接口方法时使用@Override完全没有意义。在这种情况下使用它没有任何好处——编译器已经发现了你的错误,所以这只是不必要的混乱。

当你使用Override时要小心,因为你不能在starUML之后做逆向工程;首先制作uml。

覆盖注释用于利用编译器,用于检查是否实际上覆盖了父类中的方法。如果你犯了任何错误,比如拼写错误的方法名,没有正确匹配参数的错误,它被用来通知

我认为最好在允许的情况下编写@override。它有助于编码。然而,需要注意的是,对于ecipse Helios,无论是sdk 5还是6,都允许为实现的接口方法使用@override注释。对于Galileo,无论是5还是6,@override注释都不允许。

我尽可能多地使用它来识别方法何时被覆盖。如果你看看Scala编程语言,它们也有一个override关键字。我发现它很有用。

注释确实为编译器提供了关于代码的元数据,当我们重写基类的任何方法时,注释@Override用于继承的情况。它只是告诉编译器你正在重写方法。它可以避免一些常见的错误,如没有遵循正确的方法签名或在方法名称上出错等。所以使用@Override注释是一个很好的实践。

@Override注释用于帮助开发人员检查是否重写父类或接口中的正确方法。当super的方法名发生变化时,编译器会通知这种情况,这只是为了与super和子类保持一致。

顺便说一句,如果我们没有在子类中声明注释@Override,但我们重写了super的一些方法,那么这个函数可以像@Override那样工作。但是当super的方法被更改时,这个方法不能通知开发人员。因为它不知道开发人员的目的——重写super的方法还是定义一个新方法?

因此,当我们想要重写该方法以使用多态性时,最好在该方法上方添加@Override。

对于我来说,@Override确保我有正确的方法签名。如果我放入注释,而方法拼写不正确,那么编译器会报错,让我知道有什么地方出错了。