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

你什么时候使用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注释都是不允许的。


推荐阅读

    linux控制台编程命令?

    linux控制台编程命令?,系统,工具,环境,命令,名称,标准,不了,工作,发行,基础,s

    linux编程常用命令?

    linux编程常用命令?,系统,工作,信息,命令,地址,管理,工具,网络,基础,目录,lin

    linux里面的注释命令?

    linux里面的注释命令?,地址,系统,名字,工作,命令,信息,代码,基础,情况,底部,L

    linux命令注释脚本?

    linux命令注释脚本?,代码,工具,名称,工作,脚本,发行,服务,环境,数据,基础,lin

    编程解析linux命令?

    编程解析linux命令?,系统,标准,基础,设备,发行,电脑,工具,密码,名字,适当,如

    linux脚本注释命令?

    linux脚本注释命令?,代码,系统,工作,名称,地方,脚本,命令,信息,状态,简介,lin

    linux命令标记注释?

    linux命令标记注释?,地址,基础,系统,底部,命令,文件,参数,注释,程序,控制台,3

    linux使用命令的方法?

    linux使用命令的方法?,系统,信息,工具,标准,数据,命令,左下角,目录,文件夹,

    linux命令行图形编程?

    linux命令行图形编程?,系统,不了,情况,密码,工具,地方,百度,管理,图形界面,

    linux编程执行命令?

    linux编程执行命令?,电脑,系统,环境,命令,基础,发行,工具,代码,地址,名称,lin

    linux终端命令行编程?

    linux终端命令行编程?,系统,工作,命令,终端,概念,时间,第一,代码,发行,地方,L

    linux命令行界面注释?

    linux命令行界面注释?,系统,地址,命令,地方,传播,底部,简介,概念,内核,用户,3

    linux编程调用命令?

    linux编程调用命令?,系统,标准,管理,工作,基础知识,情况,环境,设备,基础,首

    linux编程所需的命令?

    linux编程所需的命令?,工作,地址,档案,系统,命令,管理,标准,信息,目录,文件,L

    linux命令行编程乱码?

    linux命令行编程乱码?,环境,统一,乱码,中文,状态,软件,数据,系统,字符集,文

    linux打开注释命令?

    linux打开注释命令?,代码,工作,地址,网络,命令,标准,位置,图片,系统,情况,lin

    linux系统注释命令?

    linux系统注释命令?,系统,工作,地址,管理,信息,命令,目录,功能,操作,内容,lin

    linux编程c命令符?

    linux编程c命令符?,工具,代码,系统,保险,环境,文件,程序,命令,终端,编辑,到底

    linux系统命令注释?

    linux系统命令注释?,软件,工具,基础,系统,标准,命令,阅读器,文件,进程,字符