When do you use Java's @Override annotation and why?
使用Java的EDCOX1和0注释的最佳实践是什么?为什么?
似乎用
每次为两个好处而重写一个方法时都使用它。这样做,您就可以利用编译器检查的优势,确保在您认为需要重写某个方法时,您实际上正在重写该方法。这样,如果您犯了一个常见的错误,即拼错了一个方法名,或者没有正确匹配参数,您将得到警告,您的方法实际上并没有像您认为的那样重写。其次,它使代码更容易理解,因为当方法被覆盖时,它更明显。
另外,在Java 1.6中,您可以使用它来标记一个方法实现一个接口以获得相同的好处。我认为最好有一个单独的注释(如
我认为作为一个编译时提醒,该方法的目的是重写父方法是最有用的。举个例子:
1 2 3 | protected boolean displaySensitiveInformation() { return false; } |
您经常会看到类似上面的方法重写基类中的方法。这是此类的一个重要实现细节——我们不希望显示敏感信息。
假设此方法在父类中更改为
1 2 3 |
此更改不会导致任何编译时错误或警告,但会完全更改子类的预期行为。
回答您的问题:如果在超类中缺少具有相同签名的方法表示存在错误,则应使用@override注释。
这里有很多好的答案,所以让我提供另一种方式来看待它…
在编码时没有过度杀戮。键入@override并不需要花费任何代价,但是如果您拼错了方法名或是签名有点错误,则可以节省大量的成本。
这样想:在你导航到这里并输入这篇文章的时候,你用的时间比你余生输入@override的时间要多,但是它所阻止的一个错误可以节省你的时间。
Java尽其所能确保您在编辑/编译时没有犯任何错误,这是一种解决整个错误的几乎免费的方式,在综合测试之外,这些错误在任何其他方面都是不可预防的。
你能想出一个更好的Java机制来确保当用户想要重写一个方法时,他真的做到了吗?
另一个很好的效果是,如果不提供注释,它会在编译时警告您意外地覆盖了父方法——如果不打算这样做,这可能很重要。
我总是用标签。它是一个简单的编译时标志,可以捕获我可能犯的小错误。
它将捕获像
小事情对大项目有帮助。
使用
最常见的情况是,当您将基类中的方法更改为具有不同的参数列表时,这种方法非常有用。由于方法签名已更改,子类中用于重写超类方法的方法将不再这样做。这有时会导致奇怪和意外的行为,特别是在处理复杂的继承结构时。
为了利用编译器检查,您应该始终使用override注释。但是不要忘记Java编译器1.5在重写接口方法时不允许这种注释。您只需使用它来重写类方法(抽象的或非抽象的)。
一些IDES,如Eclipse,甚至配置为Java 1.6运行时或更高,它们保持与Java 1.5的一致性,并且不允许如上所述的使用@覆盖。为了避免这种行为,您必须访问:ProjtProjksProjys> Java编译器>检查"启用特定于项目的设置"->选择"编译器遵从级别"=6或更高。
如果基是接口或类,我喜欢每次独立地重写方法时都使用这个注释。
这有助于避免一些典型的错误,例如,当您认为正在重写一个事件处理程序,然后看到什么都没有发生。假设您要将事件侦听器添加到某个UI组件:
1 2 3 4 5 | someUIComponent.addMouseListener(new MouseAdapter(){ public void mouseEntered() { ...do something... } }); |
上面的代码编译并运行,但是如果您将鼠标移动到某个uicomponent中,"做些什么"代码将注意到运行,因为实际上您没有重写基方法
最好使用它作为覆盖的每一个方法,Java 6 +,每个方法作为接口的实现。
首先,它在编译时捕获像"EDOCX1"(0)这样的拼写错误,而不是"EDOCX1"(0)。当真正的原因是您的代码从未被调用时,为什么您的方法的结果似乎与您的代码不匹配,调试起来可能令人费解。
此外,如果超类更改了方法签名,则旧签名的重写可能是"孤立的",留下令人困惑的死代码。
接口实现上的重写是不一致的,因为在爪哇中没有"重写接口"之类的东西。
@对接口实现的重写是无用的,因为在实践中它不会捕获编译无论如何也不会捕获的错误。只有一个遥不可及的场景,其中对实现者的重写实际上会做一些事情:如果实现了接口,而接口删除了方法,则在编译时会通知您应该删除未使用的实现。注意,如果接口的新版本有新的或更改过的方法,那么很明显,由于没有实现新的东西,所以无论如何都会出现编译错误。
@在1.6中不应该允许对接口实现者进行覆盖,Eclipse遗憾地选择自动插入注释作为默认行为,我们得到了许多杂乱的源文件。在读取1.6代码时,如果某个方法实际重写了超类中的某个方法或只是实现了一个接口,则无法从@override注释中看到。
当实际重写超类中的方法时,可以使用@override。
@对接口的重写实际上很有用,因为如果更改接口,您将收到警告。
如果您发现自己经常重写(非抽象)方法,那么您可能需要看看您的设计。当编译器不捕获错误时,它非常有用。例如,尝试在threadlocal中重写initValue(),我已经完成了。
在实现接口方法(1.6+特性)时使用@override对我来说有点过分。如果您有很多方法,其中一些方法被重写,而另一些方法没有,那么很可能是设计错误(如果您不知道,您的编辑器可能会显示哪些方法是哪个方法)。
它所做的另一件事是,当读取代码时,它会更明显地改变父类的行为。这对调试很有帮助。
此外,在Joshua Block的《有效Java(第二版)》中,第36条给出了注释的好处的更多细节。
每当一个方法重写另一个方法,或一个方法在接口中实现签名时。
在实现接口方法时使用@override毫无意义。在这种情况下使用它没有任何好处——编译器已经捕捉到了您的错误,所以它只是不必要的混乱。
最好的实践是始终使用它(或者让IDE为您填充它们)
@重写有用性是检测尚未在层次结构中报告的父类中的更改。如果没有它,您可以更改方法签名并忘记更改其重写,使用@override,编译器将为您捕获它。
那种安全网总是很好的。
我到处都用。关于标记方法的工作的主题,我让Eclipse为我做这件事,所以这不是额外的工作。
我对连续重构很虔诚……所以,我会用每一件小事来让事情顺利进行。
我每次都用它。这是更多的信息,我可以用它来快速了解当我在一年内重新访问代码时发生了什么,我已经忘记了我第一次思考的是什么。
- 仅用于方法声明。
- 指示带批注的方法声明重写声明在超类型。
如果一直使用,它可以保护您免受一大类有害的bug的侵害。
使用@override annotation避免这些错误:(在以下代码中发现错误:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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
使用重写时要小心,因为之后不能在StarUML中进行反向工程;请先生成UML。
这里的智慧似乎正在改变。今天我安装了Intellij IDEA 9,并注意到它的"missing@override inspection"现在不仅捕获了实现的抽象方法,还捕获了实现的接口方法。在我雇主的代码库和我自己的项目中,我一直习惯于只对前者使用@override——实现抽象方法。然而,重新思考这个习惯,在这两种情况下使用注释的优点变得很明显。尽管更加冗长,但它确实保护了脆弱的基类问题(不像C++相关的例子那样严重),接口方法名称改变了,在派生类中孤立了可能实现的方法。
当然,这种情况大多是夸张的;派生类将不再编译,现在缺少重命名接口方法的实现,而今天,人们可能会使用重命名方法重构操作来集中处理整个代码基。
考虑到这个想法的检查不可配置为忽略实现的接口方法,今天我将改变我的习惯和我的团队的代码评审标准。
注释@override用于帮助检查开发人员在父类或接口中重写正确方法的内容。当super方法的名称改变时,编译器可以通知这种情况,这只是为了保持super和子类的一致性。
顺便说一句,如果我们没有在子类中声明注释@override,但是我们确实重写了super的一些方法,那么函数就可以像使用@override时那样工作。但是这个方法不能在super的方法更改时通知开发人员。因为它不知道开发人员的目的——重写super的方法或定义一个新方法?
因此,当我们想要重写该方法以利用多态性时,最好在方法上方添加@override。
我尽可能多地使用它来识别什么时候一个方法被重写。如果你看scala编程语言,它们也有一个override关键字。我觉得它很有用。
override注释用于利用编译器,检查是否确实要从父类中重写方法。它用于通知您是否犯了错误,例如错误拼写方法名、错误匹配参数
简单—当您想要重写超类中存在的方法时,使用
对于我来说,@override确保我对方法的签名是正确的。如果我输入了注释,并且方法的拼写不正确,那么编译器会抱怨让我知道有什么地方出错了。
注释确实向编译器提供了有关代码的元数据,当我们重写任何基类方法时,如果继承,则使用注释@override。它只是告诉编译器您正在重写方法。它可以避免一些常见的错误,例如不遵循方法的正确签名或方法名中的错误位置等,因此使用@override注释是一个很好的实践。
当您在要重写的方法名上使用了错误的拼写时,它确实允许您(好吧,编译器)捕获。
我认为最好在允许的时候对@override进行编码。它有助于编码。但是,需要注意的是,对于ecipse helios,无论是sdk 5还是6,都允许实现接口方法的@override注释。对于伽利略,无论是5还是6,@override注释都是不允许的。