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

When do you use Java's @Override annotation and why?

使用Java的EDCOX1和0注释的最佳实践是什么?为什么?

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


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

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


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

1
2
3
protected boolean displaySensitiveInformation() {
  return false;
}

您经常会看到类似上面的方法重写基类中的方法。这是此类的一个重要实现细节——我们不希望显示敏感信息。

假设此方法在父类中更改为

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

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

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


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

在编码时没有过度杀戮。键入@override并不需要花费任何代价,但是如果您拼错了方法名或是签名有点错误,则可以节省大量的成本。

这样想:在你导航到这里并输入这篇文章的时候,你用的时间比你余生输入@override的时间要多,但是它所阻止的一个错误可以节省你的时间。

Java尽其所能确保您在编辑/编译时没有犯任何错误,这是一种解决整个错误的几乎免费的方式,在综合测试之外,这些错误在任何其他方面都是不可预防的。

你能想出一个更好的Java机制来确保当用户想要重写一个方法时,他真的做到了吗?

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


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

它将捕获像tostring()这样的东西,而不是tostring()

小事情对大项目有帮助。


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

最常见的情况是,当您将基类中的方法更改为具有不同的参数列表时,这种方法非常有用。由于方法签名已更改,子类中用于重写超类方法的方法将不再这样做。这有时会导致奇怪和意外的行为,特别是在处理复杂的继承结构时。@Override注释对此进行了保护。


为了利用编译器检查,您应该始终使用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中,"做些什么"代码将注意到运行,因为实际上您没有重写基方法mouseEntered(MouseEvent ev)。您只需创建一个新的无参数方法mouseEntered()。如果您使用了@Override注释,则会看到编译错误,并且不会浪费时间思考事件处理程序为什么没有运行。


最好使用它作为覆盖的每一个方法,Java 6 +,每个方法作为接口的实现。

首先,它在编译时捕获像"EDOCX1"(0)这样的拼写错误,而不是"EDOCX1"(0)。当真正的原因是您的代码从未被调用时,为什么您的方法的结果似乎与您的代码不匹配,调试起来可能令人费解。

此外,如果超类更改了方法签名,则旧签名的重写可能是"孤立的",留下令人困惑的死代码。@Override注释将帮助您识别这些孤立项,以便对它们进行修改以匹配新的签名。


接口实现上的重写是不一致的,因为在爪哇中没有"重写接口"之类的东西。

@对接口实现的重写是无用的,因为在实践中它不会捕获编译无论如何也不会捕获的错误。只有一个遥不可及的场景,其中对实现者的重写实际上会做一些事情:如果实现了接口,而接口删除了方法,则在编译时会通知您应该删除未使用的实现。注意,如果接口的新版本有新的或更改过的方法,那么很明显,由于没有实现新的东西,所以无论如何都会出现编译错误。

@在1.6中不应该允许对接口实现者进行覆盖,Eclipse遗憾地选择自动插入注释作为默认行为,我们得到了许多杂乱的源文件。在读取1.6代码时,如果某个方法实际重写了超类中的某个方法或只是实现了一个接口,则无法从@override注释中看到。

当实际重写超类中的方法时,可以使用@override。


@对接口的重写实际上很有用,因为如果更改接口,您将收到警告。


如果您发现自己经常重写(非抽象)方法,那么您可能需要看看您的设计。当编译器不捕获错误时,它非常有用。例如,尝试在threadlocal中重写initValue(),我已经完成了。

在实现接口方法(1.6+特性)时使用@override对我来说有点过分。如果您有很多方法,其中一些方法被重写,而另一些方法没有,那么很可能是设计错误(如果您不知道,您的编辑器可能会显示哪些方法是哪个方法)。


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

此外,在Joshua Block的《有效Java(第二版)》中,第36条给出了注释的好处的更多细节。


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

@Override注释确保您实际上覆盖了某些内容。如果不使用注释,则可能导致参数类型和数字的拼写错误或差异。


在实现接口方法时使用@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注释是一个很好的实践。


当您在要重写的方法名上使用了错误的拼写时,它确实允许您(好吧,编译器)捕获。


我认为最好在允许的时候对@override进行编码。它有助于编码。但是,需要注意的是,对于ecipse helios,无论是sdk 5还是6,都允许实现接口方法的@override注释。对于伽利略,无论是5还是6,@override注释都是不允许的。