你什么时候使用Java的@Override注解,为什么?

什么是使用Java的@Override注释的最佳做法,为什么?

@Override注解来标记每一个重写的方法似乎是矫枉过正的。 是否有某些编程情况需要使用@Override和其他不应该使用@Override

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

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

我认为这是最有用的编译时提醒,该方法的意图是重写父方法。 举个例子:

 protected boolean displaySensitiveInformation() { return false; } 

你会经常看到类似于上面方法的东西,它覆盖了基类中的一个方法。 这是这个类的一个重要的实现细节 – 我们不希望显示敏感信息。

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

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

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

要回答你的问题:如果在超类中缺less具有相同签名的方法表示有错误,则应使用@Override注释。

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

编码时没有矫枉过正 input@override并不需要花费任何东西,但是如果拼写方法名称或签名稍微错误,节省的成本可能非常大。

这样想:当你在这里浏览并input这篇文章的时候,你会花费更多的时间,而不是在你的余生中input@override。 但是它防止的一个错误可以节省你的时间。

Java尽其所能确保您在编辑/编译时没有犯任何错误,这是一种几乎完全免费的方式来解决在全面testing之外无法以其他任何方式避免的整个类错误。

你能想出一个更好的Java机制,以确保当用户打算重写一个方法,他实际上呢?

另一个巧妙的结果是,如果你不提供注释,它会在编译时警告你,你意外地超越了父类的方法 – 如果你不打算这么做的话,这可能是重要的。

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

它会捕获像tostring()而不是toString()

这些小东西有助于大型项目。

使用@Override注解作为编译时的安全措施来防止常见的编程错误。 它会抛出一个编译错误,如果你有一个方法的注释你实际上没有重写超类的方法。

在这种情况下,最常见的情况是当你改变基类中的一个方法来获得不同的参数列表。 由于改变的方法签名,用于覆盖超类方法的子类中的方法将不再执行此操作。 这有时会导致奇怪的和意外的行为,特别是在处理复杂的inheritance结构时。 @Override注释保护这一点。

为了利用编译器检查,你应该总是使用Override注解。 但是不要忘记,在重写接口方法时,Java Compiler 1.5将不允许使用这个注解。 你可以使用它来覆盖类的方法(抽象或不)。

一些IDE,如Eclipse,甚至configuration了Java 1.6运行时或更高版本,它们保持与Java 1.5的兼容性,并且不允许如上所述使用@override。 要避免这种行为,您必须转到:项目属性 – > Java编译器 – >选中“启用项目特定设置” – >select“编译器符合级别”= 6.0或更高。

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

这可以帮助你避免一些典型的错误,比如当你正在重写一个事件处理程序,然后你什么也看不到。 想象一下,你想添加一个事件监听器到一些UI组件:

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

上面的代码编译并运行,但是如果将鼠标移动到someUIComponent中,则“执行某些”代码将会注意运行,因为实际上您不覆盖基本方法mouseEntered(MouseEvent ev) 。 您只需创build一个新的无参数方法mouseEntered() 。 而不是那个代码,如果你使用了@Override注解,你已经看到了一个编译错误,你没有浪费时间思考你的事件处理程序为什么没有运行。

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

@Override 接口实现是无用的,因为在实践中它没有捕捉到编译无法捕捉的错误。 只有一个很重要的场景,其中对实现者的重写实际上是有所作为的:如果你实现了一个接口和接口REMOVES方法,那么编译时会通知你应该删除未使用的实现。 注意,如果新版本的接口有NEW或CHANGED方法,你显然会得到一个编译错误,因为你没有实现新的东西。

@Override接口实现者应该永远不会被允许在1.6中,并且在eclipse中可悲地select自动插入注释作为默认行为,我们会得到很多混乱的源文件。 读取1.6代码时,如果某个方法实际上覆盖了超类中的某个方法,或者只是实现了一个接口,则无法从@Override注释中看到。

在实际重写超类中的方法时使用@Override是没有问题的。

最好是将其用于每种方法(旨在作为重写),而Java 6+(每种方法都用作接口的实现)。

首先,它在编译时捕获像“ hashcode() ”而不是“ hashCode() ”这样的拼写错误。 当真正的原因是你的代码从未被调用时,debugging你的方法的结果似乎不匹配你的代码可能会是莫名其妙的。

另外,如果一个超类改变了一个方法签名,旧签名的覆盖可以被“孤立”,留下来作为混淆的死代码。 @Override注释将帮助您识别这些孤儿,以便可以修改它们以匹配新的签名。

如果你经常发现自己压倒一切(非抽象)的方法,那么你可能想看看你的devise。 当编译器不会发现错误时,这是​​非常有用的。 例如试图覆盖ThreadLocal中的initValue(),我已经完成了。

实现接口方法(1.6+特性)时使用@Override对我来说似乎有些矫枉过正。 如果你有一些方法重载,有些则不重要,那么可能又是一个糟糕的devise(如果你不知道,你的编辑器可能会显示哪个是哪个)。

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

它所做的另一件事情是,当阅读改变父类行为的代码时,它会变得更加明显。 比可以帮助debugging。

此外,在Joshua Block的Effective Java(第二版)一书中,第36项给出了关于注释优点的更多细节。

实现接口方法时使用@Override是绝对没有意义的。 在这种情况下使用它没有什么好处 – 编译器已经可以捕捉到你的错误,所以这只是不必要的混乱。

每当一个方法重写另一个方法,或者一个方法在一个接口中实现一个签名。

@Override注释保证你确实覆盖了一些东西。 如果没有注释,则会导致拼写错误或参数types和编号的差异。

我每次都用它。 我可以利用更多的信息来快速了解一年中重新访问代码时发生了什么,而且我已经忘记了第一次思考的内容。

最好的方法是始终使用它(或者让IDE为你填充)

@Override的用处是检测父类的变化,这些变化还没有被报告给层次结构。 没有它,你可以改变一个方法签名,忘记改变它的覆盖,用@Override,编译器会为你捕捉它。

那种安全网总是有好处的。

我到处使用它。 关于标记方法的努力,我让Eclipse为我做了这个,这是没有额外的努力。

我对持续的重构是虔诚的……所以,我会用一切小事让它更顺利。

  • 仅用于方法声明。
  • 指示注释的方法声明覆盖超types的声明。

如果一直使用,它可以保护您免受一大类恶意程序的攻击。

使用@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

使用Override时要小心,因为之后不能在starUML中进行逆向工程; 首先使用uml。

看来这里的智慧正在改变。 今天我安装了IntelliJ IDEA 9,注意到它的“ 缺less@Override检查 ”现在不仅捕获了实现的抽象方法,而且实现了接口方法。 在我的雇主的代码库和我自己的项目中,我早就习惯于只使用@Override来实现前面实现的抽象方法。 然而,重新思考这个习惯,在这两种情况下使用注释的优点变得清晰。 尽pipe更详细一些,但它可以防止脆弱的基类问题(不像C ++相关的例子那么严重),在接口方法名称改变的地方,将派生类中的将要实现的方法孤立起来。

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

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

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

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

所以当我们想要重写这个方法来利用多态时,我们最好在方法的上面添加@Override。

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

它确实允许你(当然,编译器)抓住你在重写的方法名称上使用错误的拼写。

覆盖注释用于利用编译器,用于检查是否实际上是从父类重写一个方法。 用于通知你是否有任何错误如拼错方法名称的错误,不正确匹配参数的错误

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

注释确实向编译器提供了有关代码的元数据,当覆盖基类的任何方法时,注解@Override用于inheritance的情况。 它只是告诉编译器你正在重写方法。 它可以避免一些常见的错误,我们可以做不喜欢的方法的正确签名或方法名称mispelling等,所以它是一个很好的做法使用@Override注释。

对于我来说,@Override确保我有正确的方法的签名。 如果我在注释中,并且方法没有正确拼写,那么编译器会抱怨让我知道某些东西是错误的。

简单 – 当您想要覆盖超类中存在的方法时,请使用@Override注释来进行正确的覆盖。 编译器会警告你,如果你没有正确覆盖它。