繁体   English   中英

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

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

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

@Override注释标记每个被覆盖的方法似乎有点矫枉过正。 是否有某些编程情况需要使用@Override和其他不应该使用@Override

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

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

我认为它作为编译时提醒最有用,该方法的意图是覆盖父方法。 举个例子:

protected boolean displaySensitiveInformation() {
  return false;
}

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

假设这个方法在父类中改成

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

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

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

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

编码时没有矫枉过正。 键入@override 不会花费您任何费用,但是如果您拼错了方法名称或签名稍有错误,则节省的费用可能会很大。

这样想:在您浏览此处并输入这篇文章的时间里,您使用的时间几乎比您在余生中输入@override 所花费的时间还要多; 但它防止的一个错误可以为您节省数小时。

Java 尽其所能确保您在编辑/编译时没有犯任何错误,这是一种几乎免费的方法来解决除综合测试之外无法通过任何其他方式预防的整类错误。

您能否在 Java 中提出一种更好的机制来确保当用户打算覆盖某个方法时,他确实做到了?

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

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

它将捕获诸如tostring()而不是toString()

小事情有助于大项目。

使用@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”代码会注意到 run,因为实际上你没有覆盖基本方法mouseEntered(MouseEvent ev) 您只需创建一个新的无参数方法mouseEntered() 而不是该代码,如果您使用了@Override注释,您将看到编译错误,并且您没有浪费时间思考事件处理程序未运行的原因。

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

@Override接口实现是无用的,因为在实践中它不会捕获编译不会捕获的任何错误。 只有一种牵强附会的场景,实现者的覆盖实际上做了一些事情:如果你实现了一个接口,并且接口 REMOVES 方法,你将在编译时收到通知,你应该删除未使用的实现。 请注意,如果新版本的接口有 NEW 或 CHANGED 方法,您显然会收到编译错误,因为您没有实现新东西。

@Override 在 1.6 中永远不应该被允许,并且 eclipse 遗憾地选择自动插入注释作为默认行为,我们得到了很多杂乱的源文件。 在阅读 1.6 代码时,从 @Override 注释中看不到一个方法是实际覆盖了超类中的方法还是只是实现了一个接口。

在实际覆盖超类中的方法时使用 @Override 很好。

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

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

此外,如果超类更改了方法签名,则旧签名的覆盖可能会“孤立”,留下令人困惑的死代码。 @Override注释将帮助您识别这些孤儿,以便可以修改它们以匹配新签名。

如果您发现自己经常覆盖(非抽象)方法,您可能想看看您的设计。 当编译器不会以其他方式捕获错误时,它非常有用。 例如,尝试在 ThreadLocal 中覆盖 initValue(),我已经完成了。

在实现接口方法(1.6+ 功能)时使用 @Override 对我来说似乎有点矫枉过正。 如果您有大量方法,其中一些方法会被覆盖,而另一些不会,那可能又是糟糕的设计(如果您不知道,您的编辑器可能会显示哪个是哪个)。

@Override 在接口上实际上是有帮助的,因为如果您更改接口,您将收到警告。

它所做的另一件事是在阅读代码时更明显地看出它正在改变父类的行为。 比可以帮助调试。

此外,在 Joshua Block 的《Effective Java》(第 2 版)一书中,第 36 条提供了有关注释优势的更多详细信息。

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

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

@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

我每次都用它。 当我在一年内重新访问代码并且我已经忘记了我第一次在想什么时,我可以使用更多信息来快速弄清楚发生了什么。

最好的做法是始终使用它(或让 IDE 为您填写)

@Override 的用处是检测尚未在层次结构中报告的父类中的更改。 没有它,您可以更改方法签名而忘记更改其覆盖,使用@Override,编译器会为您捕获它。

拥有这种安全网总是好的。

我到处都用它。 关于标记方法的工作主题,我让 Eclipse 为我做,所以没有额外的工作。

我对持续重构很虔诚……所以,我会用每一件小事让它更顺利。

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

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

当然,这个场景大多是夸张的; 派生类将不再编译,现在缺少重命名接口方法的实现,今天人们可能会使用重命名方法重构操作来解决整个代码库。

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

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

顺便说一句,如果我们没有在子类中声明@Override 注释,但我们确实覆盖了super 的一些方法,那么该函数可以与@Override 一起工作。 但是这个方法不能在super的方法改变时通知开发者。 因为它不知道开发者的目的——覆盖super的方法还是定义一个新的方法?

因此,当我们想覆盖该方法以利用多态性时,最好在方法上方添加@Override。

我尽可能多地使用它来确定何时覆盖方法。 如果您查看 Scala 编程语言,它们还有一个 override 关键字。 我觉得很有用。

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

覆盖注释用于利用编译器,检查您是否确实覆盖了父类中的方法。 它用于通知您是否犯了任何错误,例如错误拼写方法名称的错误,未正确匹配参数的错误

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

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

对我来说,@Override 确保我拥有正确的方法签名。 如果我输入了注释并且方法拼写不正确,那么编译器会抱怨让我知道某些地方有问题。

它确实允许您(好吧,编译器)在您对要覆盖的方法名称使用错误拼写时进行捕获。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM