Когда вы используете аннотацию Java @Override и почему?

Каковы лучшие практики использования аннотации Java @Override и почему?

Похоже, было бы излишним отмечать каждый переопределенный метод аннотацией @Override. Существуют ли определенные ситуации программирования, которые требуют использования @Override и других, которые никогда не должны использовать @Override?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
498
0
905 954
27
Перейти к ответу Данный вопрос помечен как решенный

Ответы 27

Использую каждый раз. Это больше информации, которую я могу использовать, чтобы быстро понять, что происходит, когда я пересматриваю код через год и я забыл, о чем думал в первый раз.

Я всегда использую тег. Это простой флаг времени компиляции, позволяющий отловить небольшие ошибки, которые я могу сделать.

Он будет ловить такие вещи, как tostring() вместо toString()

Мелочи помогают в больших проектах.

Каждый раз, когда метод переопределяет другой метод или метод реализует подпись в интерфейсе.

Аннотация @Override заверяет вас, что вы действительно что-то переопределили. Без аннотации вы рискуете орфографической ошибкой или различием в типах и количестве параметров.

Вы можете использовать его только для обозначения реализации интерфейса в Java 1.6.

Dave L. 18.09.2008 20:55

Это позволяет вам (ну, компилятору) обнаруживать неправильное написание имени метода, который вы переопределяете.

Ответ принят как подходящий

Используйте его каждый раз, когда переопределяете метод для получения двух преимуществ. Сделайте это так, чтобы вы могли воспользоваться проверкой компилятора, чтобы убедиться, что вы действительно переопределяете метод, когда вы думаете, что это так. Таким образом, если вы сделаете типичную ошибку, неправильно написав имя метода или неверно сопоставив параметры, вы будете предупреждены о том, что ваш метод на самом деле не переопределяет, как вы думаете. Во-вторых, это облегчает понимание вашего кода, потому что это более очевидно, когда методы перезаписываются.

Кроме того, в Java 1.6 вы можете использовать его, чтобы отмечать, когда метод реализует интерфейс для тех же преимуществ. Думаю, было бы лучше иметь отдельную аннотацию (например, @Implements), но это лучше, чем ничего.

В том же духе, что и «проще для понимания», IDE обнаруживают аннотацию @Override и визуально отмечают метод переопределения в редакторе.

Bob Cross 19.09.2008 17:26

Некоторые IDE помечают переопределенный метод, в котором также отсутствует аннотация @Override.

Jay R. 20.09.2008 18:48

Другое преимущество заключается в том, что при изменении родительского класса компилятор будет следить за тем, чтобы дочерние классы также были обновлены.

David 27.05.2009 19:58

@ Джей Р .: Верно. На самом деле, например, Eclipse может даже автоматически добавить @Override, если он отсутствует.

sleske 08.10.2009 20:01

В случае, если кто-то еще попал сюда из-за явно недокументированного изменения с 1.5 на 1.6 для @Overrides в методах, поступающих из интерфейсов, bugs.sun.com/bugdatabase/view_bug.do?bug_id=5008260 кажется соответствующей ошибкой. (Спасибо, что указали на это, Дэйв Л.!)

Henrik Heimbuerger 23.01.2010 21:23

Вроде та же ситуация, что и с исключениями throws-keyword. Нам был предоставлен такой большой контроль, что последняя тенденция заключается в наследовании от RuntimeException, чтобы не думать об исключении больше, чем о логике приложения.

sergtk 14.02.2011 12:39

@hheimbuerger Спасибо, чувак, мне действительно было интересно, шутит ли Eclipse ... потом я погуглил и пришел прямо сюда ... снова. Я уже проголосовал за ваш комментарий ... да

dertoni 24.08.2011 18:41

эй, лет, и просто помог мне понять, что мой код 1.5 и пометил ошибку для переопределения в методе интерфейса;)

definitely undefinable 07.10.2011 12:46

Вы можете настроить Eclipse для автоматической вставки отсутствующих аннотаций @Override: см. Проект> Сохранить действия> Настроить.

Rok Strniša 22.11.2011 22:35

Ваш комментарий о @Implements совпал с моими мыслями. Я пришел сюда, чтобы узнать, подходит ли @Override для методов реализации, и из того, что я здесь понял, это так. Спасибо. Согласен, что @Implements будет лучше. Это также вызовет меньше путаницы.

Xonatron 13.02.2012 23:42

Использование аннотации @Override действует как защита во время компиляции от распространенной ошибки программирования. Это вызовет ошибку компиляции, если у вас есть аннотация к методу, который на самом деле не переопределяет метод суперкласса.

Наиболее распространенный случай, когда это полезно, - это когда вы меняете метод в базовом классе, чтобы иметь другой список параметров. Метод в подклассе, который использовался для переопределения метода суперкласса, больше не будет делать этого из-за измененной сигнатуры метода. Иногда это может вызывать странное и неожиданное поведение, особенно при работе со сложными структурами наследования. Аннотации @Override защищают от этого.

Лучший ответ. Коротко и мило. Хотел бы я, чтобы вы могли объяснить, как работает "гарантия" ... никто этого не объяснил.

djangofan 23.11.2011 23:13

Это просто объяснить. Если вы сделаете ошибку (изменив интерфейс, абстрактный класс или подкласс, вы получите либо предупреждение (например, в Eclipse), либо ошибку времени компиляции, сообщающую вам, что ваш @Override не работает. Фактическая ошибка сообщение будет зависеть от того, что было изменено, но в Eclipse (например) очень быстро становится ясно, что есть проблема: вы увидите маленькое красное зигзагообразное подчеркивание, а наведение курсора на оскорбительный текст скажет вам, что не так. Я называю это хорошей ценностью.

Ichiro Furusato 17.01.2012 04:40

Если вы очень часто обнаруживаете, что переопределяете (не абстрактные) методы, вы, вероятно, захотите взглянуть на свой дизайн. Это очень полезно, когда компилятор иначе не обнаружил бы ошибку. Например, попытка переопределить initValue () в ThreadLocal, что я и сделал.

Использование @Override при реализации методов интерфейса (функция 1.6+) кажется мне излишним. Если у вас есть множество методов, некоторые из которых переопределяют, а некоторые нет, это, вероятно, снова плохой дизайн (и ваш редактор, вероятно, покажет, какие из них, если вы не знаете).

Собственно, это также хорошо для переопределения методов интерфейса. Если я, например, удалите старый, устаревший метод из интерфейса, этот метод также следует удалить из всех реализующих классов - их легко обнаружить, если они используют @override.

Dominik Sandjaja 12.08.2010 12:47

Лучшая практика - всегда использовать его (или пусть IDE заполнит их за вас)

Полезность @Override заключается в обнаружении изменений в родительских классах, о которых не было сообщено по иерархии. Без него вы можете изменить сигнатуру метода и забыть изменить его переопределения, с @Override компилятор поймает это за вас.

Такого рода страховочную сетку всегда хорошо иметь.

Итак, если вы измените родительский метод и не используете @Override в методе дочернего класса, компиляция скажет что-нибудь или промолчит? Дает ли вам больше информации использование «Переопределения», и если да, то что?

djangofan 23.11.2011 23:16

Я думаю, что это наиболее полезно в качестве напоминания во время компиляции о том, что целью метода является переопределение родительского метода. В качестве примера:

protected boolean displaySensitiveInformation() {
  return false;
}

Вы часто будете видеть что-то вроде вышеуказанного метода, который переопределяет метод в базовом классе. Это важная деталь реализации этого класса - мы не хотим, чтобы отображалась конфиденциальная информация.

Предположим, этот метод изменен в родительском классе на

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

Это изменение не вызовет никаких ошибок или предупреждений во время компиляции, но полностью меняет предполагаемое поведение подкласса.

Чтобы ответить на ваш вопрос: вы должны использовать аннотацию @Override, если отсутствие метода с такой же сигнатурой в суперклассе указывает на ошибку.

@Override на интерфейсах действительно полезны, потому что вы получите предупреждения, если измените интерфейс.

Я везде им пользуюсь. Что касается усилий по маркировке методов, я позволил Eclipse сделать это за меня, так что это не требует дополнительных усилий.

Я религиозен в отношении непрерывного рефакторинга ... так что я буду использовать каждую мелочь, чтобы сделать его более гладким.

Лучше всего использовать его для каждого метода, предназначенного для переопределения, а в Java 6+ - для каждого метода, предназначенного для реализации интерфейса.

Во-первых, он обнаруживает орфографические ошибки, такие как «hashcode()» вместо «hashCode()» во время компиляции. Может быть затруднительно отладить, почему результат вашего метода не соответствует вашему коду, когда настоящая причина заключается в том, что ваш код никогда не вызывается.

Кроме того, если суперкласс изменяет сигнатуру метода, переопределения старой сигнатуры могут быть «осиротевшими», оставив их как запутанный мертвый код. Аннотация @Override поможет вам идентифицировать этих сирот, чтобы их можно было изменить в соответствии с новой подписью.

Здесь есть много хороших ответов, поэтому позвольте мне предложить другой способ взглянуть на это ...

Когда вы пишете код, нет ничего лишнего. Вам ничего не нужно набирать @override, но экономия может быть огромной, если вы неправильно написали имя метода или неправильно указали подпись.

Подумайте об этом так: за то время, когда вы перешли сюда и набрали этот пост, вы потратили гораздо больше времени, чем вы потратите на ввод @override всю оставшуюся жизнь; но одна ошибка, которую он предотвращает, может сэкономить вам часы.

Java делает все возможное, чтобы убедиться, что вы не допустили никаких ошибок во время редактирования / компиляции, это практически бесплатный способ решить целый класс ошибок, которые невозможно предотвратить никаким другим способом, кроме всестороннего тестирования.

Не могли бы вы придумать лучший механизм в Java, чтобы гарантировать, что когда пользователь намеревается переопределить метод, он действительно это делает?

Еще один интересный эффект заключается в том, что если вы не предоставите аннотацию, она предупредит вас во время компиляции о том, что вы случайно переопределили родительский метод - что может иметь значение, если вы не собирались этого делать.

«Когда ты кодируешь, нет лишнего». Я согласен с этим, поэтому я считаю, что динамические языки настолько неправильны (хотя сейчас 100% моей оплачиваемой работы выполняется на Ruby).

Dan Rosenstark 10.01.2010 21:14

+1: Возможно, у меня было 10 ошибок, вызванных ошибкой при переопределении - время, необходимое для поиска любой из них, легко превысило бы время, необходимое для ввода @Override для каждого из моих методов переопределения. Кроме того, если @Override является обременительным, вы, вероятно, чрезмерно используете наследование.

Lawrence Dol 27.03.2010 20:24

Один очень реальный недостаток состоит в том, что вы усложняете чтение кода, засоряя его улитками. Возможно, это вина моей IDE, но я испытал это на себе.

treat your mods well 29.04.2010 00:15

@phyzome это не может быть так ужасно, как реализация универсального класса - иногда даже использование универсального класса, кажется, делает код практически нечитаемым. Поскольку (как вы говорите) аннотации обычно не интересны программистам, возможно, можно сказать eclipse, чтобы они скрывались?

Bill K 29.04.2010 00:19

@phyzome Если вы находите "Snails" громоздкими, значит, вы не используете НИГДЕ РЯДОМ достаточно комментариев. Они должны быть просто одной строкой над заголовком вашего метода, который в большинстве случаев должен быть примерно такого же размера, как ваш метод (несколько строк), чтобы обеспечить достойный текст при наведении курсора и javadocs. Думаю, я говорю, что проблема не в Улитках, а в ваших привычках к чтению. Вас тоже беспокоят все эти скобки в коде?

Bill K 19.08.2010 21:56

Я не согласен. В старых версиях Java / Eclipse аннотация будет выдавать ошибку «Метод ... типа ... должен переопределять метод суперкласса»

rds 25.03.2011 18:23

Да, в коде есть излишества: когда вы пишете комментарии, которые просто повторяют то, что явно делает код.

Ants 23.03.2012 11:38

@Ants Я слышал это раньше, но никогда этого не видел (или это было довольно минимально), большинство людей просто используют эту фразу как оправдание, чтобы оправдать отсутствие комментариев, но вы, возможно, работали с разными людьми / группами с разными стандартами . Кроме того, если в комментариях на английском написано то, что код говорит кодировкой, и большинство разработчиков, которые следят за ним, могут сэкономить 3 секунды, анализируя эту строку, неплохо было бы потратить 5 секунд на ее ввод.

Bill K 25.03.2012 03:27

@ Билл К. См. refactormycode.com/codes/2025-numerical-methods-secant-metho‌ d. Посмотрите комментарии к строкам, где x0 и x1 подготовлены к следующей итерации.

Ants 28.03.2012 12:54

@Ants Это избыточно, но совсем не вредно (тем более, что они помещают его в ту же строку в этом случае), тогда как большую часть времени, когда кто-то жалуется на такой код, он оправдывает отсутствие комментариев, которые могут быть более серьезными. вредный. Я делал подобные вещи в тех случаях, когда я сначала записывал то, что хочу, в псевдокоде, а затем возвращался и заполнял реальным кодом. Иногда работает как организационный инструмент, и, как правило, лучше оставлять комментарии, но иногда они оказываются немного избыточными. Если у вас сформировалась пожизненная привычка, откажитесь от чрезмерных комментариев.

Bill K 31.03.2012 01:48

Еще он делает более очевидным при чтении кода, что он меняет поведение родительского класса. Чем может помочь в отладке.

Кроме того, в статье Джошуа Блока «Эффективная Java» (2-е издание), пункт 36 дает более подробную информацию о преимуществах аннотации.

@Override на реализация интерфейса несовместим, поскольку в java нет такой вещи, как «переопределение интерфейса».

@Override на реализация интерфейса бесполезен, поскольку на практике он не обнаруживает ошибок, которые компиляция все равно не поймала бы. Существует только один, надуманный сценарий, в котором переопределение средств реализации действительно что-то делает: если вы реализуете интерфейс, а методы интерфейса REMOVES, вы будете уведомлены во время компиляции, что вам следует удалить неиспользуемые реализации. Обратите внимание, что если новая версия интерфейса имеет методы NEW или CHANGED, вы, очевидно, все равно получите ошибку компиляции, поскольку вы не реализуете новый материал.

@Override в разработчиках интерфейса никогда не должен был быть разрешен в 1.6, и с тем, что eclipse, к сожалению, выбрал автоматическую вставку аннотаций в качестве поведения по умолчанию, мы получаем много загроможденных исходных файлов. При чтении кода 1.6 вы не можете увидеть из аннотации @Override, действительно ли метод переопределяет метод в суперклассе или просто реализует интерфейс.

Использование @Override при фактическом переопределении метода в суперклассе - это нормально.

По этому поводу существуют разные мнения. См. stackoverflow.com/questions/212614/….

sleske 08.10.2009 20:04

Чтобы воспользоваться проверкой компилятора, вы всегда должны использовать аннотацию Override. Но не забывайте, что Java Compiler 1.5 не разрешает эту аннотацию при переопределении методов интерфейса. Вы просто можете использовать его для переопределения методов класса (абстрактных или нет).

Некоторые IDE, такие как Eclipse, даже настроенные на среду выполнения Java 1.6 или выше, поддерживают совместимость с Java 1.5 и не позволяют использовать @override, как описано выше. Чтобы избежать такого поведения, вы должны перейти к: «Свойства проекта» -> «Компилятор Java» -> «Включить параметры для конкретного проекта» -> «Выбрать уровень соответствия компилятора» = 6.0 или выше.

Мне нравится использовать эту аннотацию каждый раз, когда я переопределяю метод независимо, если базой является интерфейс или класс.

Это помогает избежать некоторых типичных ошибок, например, когда вы думаете, что переопределяете обработчик событий, а затем ничего не видите. Представьте, что вы хотите добавить прослушиватель событий к некоторому компоненту пользовательского интерфейса:

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

Приведенный выше код компилируется и запускается, но если вы переместите указатель мыши внутри someUIComponent, код «что-то сделать» отметит запуск, потому что на самом деле вы не переопределяете базовый метод mouseEntered(MouseEvent ev). Вы просто создаете новый метод без параметров mouseEntered(). Вместо этого кода, если вы использовали аннотацию @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

Я не знаю, каковы правила приоритета операторов в Java, но ваш метод equals кричит БУУУУУУУУУУУГ! Я бы написал (b.first == first) && (b.second == second), даже если бы && имел более низкий приоритет, чем ==.

pyon 02.10.2009 20:51

Знаете ли вы, что ваша ссылка показывает сообщение «вы должны подписаться», охватывающее полезную часть этой страницы?

Adriano Varoli Piazza 07.11.2009 17:43

@ Адриано: Извини, чувак !! Беспомощен !! Когда я написал «ответ», он был доступен. Не беспокойтесь .. купите книгу. Оно того стоит !!

jai 07.11.2009 19:38

Метод equals не переопределяет: исходный Object::equals - это boolean equals(Object), а переопределенный equals - это boolean equals(Bigram), который имеет другую сигнатуру метода, которая не отменяет. Добавление @Override к equals обнаружит эту ошибку.

Ming-Tang 12.08.2010 03:45

Кажется, что мудрость здесь меняется. Сегодня я установил IntelliJ IDEA 9 и заметил, что его "отсутствует проверка @Override" теперь улавливает не только реализованные абстрактные методы, но и реализованные методы интерфейса. В кодовой базе моего работодателя и в моих собственных проектах я давно имел привычку использовать @Override только для ранее реализованных абстрактных методов. Однако, если переосмыслить привычку, становится ясна заслуга использования аннотаций в обоих случаях. Несмотря на то, что он более подробный, он действительно защищает от проблемы хрупкий базовый класс (не такой серьезной, как в примерах, связанных с C++), когда имя метода интерфейса изменяется, что лишает потенциальный метод реализации в производном классе.

Конечно, этот сценарий по большей части преувеличен; производный класс больше не будет компилироваться, в нем теперь отсутствует реализация переименованного метода интерфейса, и сегодня, вероятно, можно было бы использовать операцию рефакторинга Переименовать метод для массового обращения ко всей базе кода.

Учитывая, что проверка IDEA не настраивается на игнорирование реализованных методов интерфейса, сегодня я изменю как свою привычку, так и критерии проверки кода моей команды.

Просто - если вы хотите переопределить метод, присутствующий в вашем суперклассе, используйте аннотацию @Override, чтобы сделать правильное переопределение. Компилятор предупредит вас, если вы не переопределите его правильно.

Совершенно бессмысленно использовать @Override при реализации метода интерфейса. В этом случае нет никаких преимуществ в использовании - компилятор уже поймает вашу ошибку, так что это просто ненужный беспорядок.

Использование @Override в интерфейсе заставит вас заметить, когда метод в интерфейсе удален.

Alex B 27.01.2010 18:24

@Alex: Удаление методов в интерфейсе - это критическое изменение, как и их добавление. После публикации интерфейса он фактически блокируется, если вы не имеете полного контроля над всем используемым им кодом.

Lawrence Dol 27.03.2010 20:21

Будьте осторожны при использовании Override, потому что после этого вы не сможете выполнить обратный инжиниринг в starUML; сначала сделайте uml.

Аннотация Override используется, чтобы воспользоваться преимуществами компилятора, чтобы проверить, действительно ли вы переопределяете метод из родительского класса. Он используется для уведомления, если вы сделаете какую-либо ошибку, например ошибку неправильного написания имени метода, ошибку неправильного сопоставления параметров

Я думаю, что лучше всего кодировать @override, когда это разрешено. это помогает при кодировании. однако следует отметить, что для ecipse Helios, sdk 5 или 6, допускается аннотация @override для реализованных методов интерфейса. что касается Галилео, либо 5, либо 6, аннотация @override не допускается.

Я использую его как можно чаще, чтобы определить, когда метод переопределяется. Если вы посмотрите на язык программирования Scala, у них также есть ключевое слово override. Я считаю это полезным.

Аннотации предоставляют метаданные о коде компилятору, а аннотация @Override используется в случае наследования, когда мы переопределяем любой метод базового класса. Он просто сообщает компилятору, что вы переопределяете метод. Это может избежать некоторых типичных ошибок, которые мы можем сделать, например, несоблюдение правильной сигнатуры метода или неправильное написание имени метода и т. д. Поэтому рекомендуется использовать аннотацию @Override.

Аннотация @Override используется, чтобы помочь проверить, может ли разработчик переопределить правильный метод в родительском классе или интерфейсе. Когда имя методов super изменяется, компилятор может уведомить об этом случае, что только для обеспечения согласованности с super и подклассом.

Кстати, если мы не объявляем аннотацию @Override в подклассе, но мы переопределяем некоторые методы супер, тогда функция может работать как эта с @Override. Но этот метод не может уведомить разработчика об изменении метода супер. Потому что он не знал цели разработчика - переопределить метод super или определить новый метод?

Поэтому, когда мы хотим переопределить этот метод, чтобы использовать полиморфизм, нам лучше добавить @Override над методом.

Для меня @Override гарантирует, что у меня правильная подпись метода. Если я добавляю аннотацию, а метод написан неправильно, компилятор жалуется, давая мне знать, что что-то не так.

Другие вопросы по теме