В этой статье я рассмотрю различия в трех «общих» методах [ equals (Object) , hashCode () и toString () ], сгенерированных NetBeans 8.0.2 , IntelliJ IDEA 14.0.2 и Eclipse Luna 4.4.1 , Цель состоит не в том, чтобы определить, что лучше, а в том, чтобы показать различные подходы, которые можно использовать для реализации этих общих методов. По пути, некоторые интересные идеи могут быть получены относительно создания этих общих методов, основанных на том, что IDE предполагают и побуждают разработчика устанавливать.
NetBeans 8.0.2
NetBeans 8.0.2 позволяет настроить свойства проекта для поддержки платформы JDK 8 и ожидать форматирования источника JDK 8, как показано на следующих двух снимках экрана.
Код генерируется в NetBeans 8.0.2, нажав Source | Вставить код (или сочетание клавиш Alt + Insert).
При создании методов equals(Object)
, hashCode()
и toString()
NetBeans 8.0.2 запрашивает атрибуты, которые будут использоваться в каждом из этих сгенерированных методов, как показано на следующих двух снимках экрана.
Методы, сгенерированные NetBeans, используют преимущества класса Objects, представленного в JDK 7 .
Генерируемый методом NetBeans метод hashCode () для класса NetBeans802GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
|
@Override public int hashCode() { int hash = 5 ; hash = 29 * hash + Objects.hashCode( this .someString); hash = 29 * hash + Objects.hashCode( this .timeUnit); hash = 29 * hash + this .integer; hash = 29 * hash + Objects.hashCode( this .longValue); return hash; } |
Метод equals (Object), сгенерированный NetBeans для класса NetBeans802GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Override public boolean equals(Object obj) { if (obj == null ) { return false ; } if (getClass() != obj.getClass()) { return false ; } final NetBeans802GeneratedCommonMethods other = (NetBeans802GeneratedCommonMethods) obj; if (!Objects.equals( this .someString, other.someString)) { return false ; } if ( this .timeUnit != other.timeUnit) { return false ; } if ( this .integer != other.integer) { return false ; } if (!Objects.equals( this .longValue, other.longValue)) { return false ; } return true ; } |
Генерируемый методом NetBeans метод toString () для класса NetBeans802GeneratedCommonMethods.java
1
2
3
4
5
|
@Override public String toString() { return "NetBeans802GeneratedCommonMethods{" + "someString=" + someString + ", timeUnit=" + timeUnit + ", integer=" + integer + ", longValue=" + longValue + '}' ; } |
Некоторые замечания можно сделать относительно общих методов, генерируемых NetBeans:
- Весь сгенерированный код является автоматическим и не поддерживает настройку, за исключением полей, используемых в методах, которые выбирает оператор.
- Все эти распространенные методы, расширяющие аналоги в классе
Object
автоматически имеют аннотацию@Override
. - Никакая документация Javadoc не включена для сгенерированных методов.
- Методы используют класс
Objects
чтобы сделать сгенерированный код более лаконичным с меньшей потребностью в нулевых проверках. - Для String, генерируемой
toString()
поддерживается только один формат, и этот выходной формат представляет собой одну строку, разделенную запятой. - Я не показывал это в приведенном выше примере, но генерация методов NetBeans 8.0.2 в некоторых случаях обрабатывает массивы иначе, чем ссылки, перечисления и примитивы:
- Сгенерированный метод
toString()
обрабатывает атрибуты массива экземпляра так же, как он обрабатывает другие атрибуты экземпляра: он опирается на методtoString()
массива, что приводит к часто нежелательным и обычно бесполезным результатам ( хэш-код идентификатора системы массива). Как правило, предпочтительнее иметь строковое содержимое атрибутов массива, предоставляемое Arrays.toString (Object []) или эквивалентной перегруженной версией или Arrays.deepToString (Object []) . - Сгенерированный метод
hashCode()
использует Arrays.deepHashCode (Object []) для обработки хеш-кодов массивов. - Сгенерированный метод
equals(Object)
использует Arrays.deepEquals (Object [], Object []) для обработки проверок на равенство массивов. - Здесь стоит подчеркнуть, что NetBeans использует «глубокие» версии методов Arrays для сравнения массивов на равенство и вычисления хеш-кодов массивов, в то время как IntelliJ IDEA и Eclipse используют обычные (не глубокие) версии методов
Arrays
для сравнения массивов на равенство и вычисление хеш-кодов массивов.
- Сгенерированный метод
IntelliJ IDEA 14.0.2
Для этих примеров я использую IntelliJ IDEA 14.0.2 Community Edition .
IntelliJ IDEA 14.0.2 предоставляет возможность настроить структуру проекта так, чтобы он ожидал «языковой уровень» JDK 8.
Для генерации кода в IntelliJ IDEA 14.0.2 используется код | Создайте параметры (или клавиши Alt + Insert, как NetBeans).
IntelliJ IDEA 14.0.2 запрашивает оператор, для которого атрибуты должны быть включены в сгенерированные методы. Он также спрашивает, какие поля не являются нулевыми, означая, что поля, как предполагается, никогда не будут нулевыми. На снимке, показанном здесь, они проверяются, что приводит к тому, что методы не проверяют эти атрибуты на null, прежде чем пытаться получить к ним доступ. Однако в коде, который я сгенерирую с помощью IntelliJ IDEA для этого поста, я не проверю их, а это означает, что IntelliJ IDEA будет проверять наличие нуля, прежде чем обращаться к ним в сгенерированных методах.
Генерация toString()
IntelliJ IDEA 14.0.2 предоставляет длинный список форматов (шаблонов) для сгенерированного метода toString()
.
IntelliJ IDEA 14.0.2 также позволяет оператору выбирать атрибуты, которые будут включены в сгенерированный метод toString()
(выбирается, когда выделенный фон имеет синий цвет).
Генерируемый IDEA метод equals (Object) для класса Idea1402GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public boolean equals(Object o) { if ( this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Idea1402GeneratedCommonMethods that = (Idea1402GeneratedCommonMethods) o; if (integer != that.integer) return false ; if (longValue != null ? !longValue.equals(that.longValue) : that.longValue != null ) return false ; if (someString != null ? !someString.equals(that.someString) : that.someString != null ) return false ; if (timeUnit != that.timeUnit) return false ; return true ; } |
Генерируемый методом IDEA метод hashCode () для класса Idea1402GeneratedCommonMethods.java
1
2
3
4
5
6
7
8
9
|
@Override public int hashCode() { int result = someString != null ? someString.hashCode() : 0 ; result = 31 * result + (timeUnit != null ? timeUnit.hashCode() : 0 ); result = 31 * result + integer; result = 31 * result + (longValue != null ? longValue.hashCode() : 0 ); return result; } |
Генерируемый IDEA метод toString () для класса Idea1402GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
|
@Override public String toString() { return "Idea1402GeneratedCommonMethods{" + "someString='" + someString + '\ '' + ", timeUnit=" + timeUnit + ", integer=" + integer + ", longValue=" + longValue + '}' ; } |
Некоторые замечания могут быть сделаны относительно общих методов, сгенерированных IntelliJ IDEA:
- Большая часть сгенерированного кода является автоматической с незначительной доступной настройкой, включая поля, используемые в методах, которые выбирает оператор, спецификация полей, которые, как ожидается, будут ненулевыми (так что проверки с нулем не нужны в сгенерированном коде), и возможность выбора один из восьми встроенных форматов
toString()
. - Все эти распространенные методы, расширяющие аналоги в классе
Object
автоматически имеют аннотацию@Override
. - Никакая документация Javadoc не включена для сгенерированных методов.
- Сгенерированные методы не используют класс
Objects
и поэтому требуют явных проверок на нулевое значение для всех ссылок, которые могут быть нулевыми. - В приведенном выше примере это не показано, но IntelliJ IDEA 14.0.2 действительно обрабатывает массивы по-разному при генерации этих трех распространенных методов:
- Сгенерированный метод
toString()
использует Arrays.toString (Array) для массива. - Сгенерированный метод
hashCode()
использует Arrays.hashCode (Object []) (или перегруженную версию) в массиве. - Сгенерированный метод
equals(Object)
использует Arrays.equals (Object [], Object []) (или перегруженную версию) в массиве.
- Сгенерированный метод
Затмение Луны 4.4.1
Eclipse Luna 4.4.1 позволяет установить для компилятора Java в свойствах проекта значение JDK 8.
В Eclipse Luna разработчик использует раскрывающийся список «Источник», чтобы выбрать конкретный тип генерации исходного кода, который необходимо выполнить.
Eclipse Luna позволяет оператору выбирать атрибуты, которые будут включены в общие методы. Это также позволяет оператору указать несколько характеристик генерируемых методов. Например, оператор может выбрать, чтобы элементы массива печатались индивидуально в сгенерированном методе toString()
а не представляли часто бессмысленное имя класса и системный идентификатор хеш-кода.
Генерируемый Eclipse метод hashCode () для класса Eclipse441GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
/* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31 ; int result = 1 ; result = prime * result + this .integer; result = prime * result + (( this .longValue == null ) ? 0 : this .longValue.hashCode()); result = prime * result + (( this .someString == null ) ? 0 : this .someString.hashCode()); result = prime * result + (( this .timeUnit == null ) ? 0 : this .timeUnit.hashCode()); return result; } |
Генерируемый Eclipse метод equals (Object) для класса Eclipse441GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
/* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if ( this == obj) return true ; if (obj == null ) return false ; if (getClass() != obj.getClass()) return false ; Eclipse441GeneratedCommonMethods other = (Eclipse441GeneratedCommonMethods) obj; if ( this .integer != other.integer) return false ; if ( this .longValue == null ) { if (other.longValue != null ) return false ; } else if (! this .longValue.equals(other.longValue)) return false ; if ( this .someString == null ) { if (other.someString != null ) return false ; } else if (! this .someString.equals(other.someString)) return false ; if ( this .timeUnit != other.timeUnit) return false ; return true ; } |
Генерируемый Eclipse метод toString () для класса Eclipse441GeneratedCommonMethods.java
01
02
03
04
05
06
07
08
09
10
|
/* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Eclipse441GeneratedCommonMethods [someString=" + this .someString + ", timeUnit=" + this .timeUnit + ", integer=" + this .integer + ", longValue=" + this .longValue + "]" ; } |
Некоторые замечания могут быть сделаны относительно общих методов, генерируемых Eclipse:
- Eclipse обеспечивает большинство точек в процессе генерации, в которых можно сконфигурировать сгенерированный вывод. Вот некоторые из настраиваемых параметров:
- Расположение в классе (до или после существующих методов класса) может быть указано явно.
- Все эти распространенные методы, расширяющие аналоги в классе
Object
автоматически имеют аннотацию@Override
. - «Комментарии к методу» могут быть сгенерированы, но они не являются комментариями в стиле Javadoc (используйте
/*
вместо/**
и явно заявляйте, что они не являются комментариями Javadoc как часть сгенерированного комментария). - Опция «перечислять содержимое массивов вместо использования встроенного toString ()» позволяет разработчику использовать Arrays.toString (Array) (аналогично подходу IntelliJ IDEA и происходит в случае его проверки) или использовать системный идентификационный хеш-код (такой же, как Подход NetBeans и происходит, если не проверено).
- Поддержка четырех стилей
toString()
плюс возможность указать собственный стиль. - Возможность ограничить количество записей в массиве, коллекции или карте, которые печатаются в
toString()
. - Возможность использовать экземпляр в сгенерированной реализации
equals(Object)
.
- Все эти распространенные методы, расширяющие аналоги в классе
Object
автоматически имеют аннотацию@Override
. - Сгенерированные методы не используют класс
Objects
и поэтому требуют явных проверок на нулевое значение для всех ссылок, которые могут быть нулевыми. - Eclipse Luna 4.4.1 действительно обрабатывает массивы по-разному при генерации трех общих методов, выделенных в этом посте:
- Сгенерированный
toString()
дополнительно используетArrays.toString(Object[])
или перегруженную версию для доступа к содержимому массива. - Созданный
equals(Object)
используетArrays.equals(Object[], Object[])
или перегруженную версию для сравнения массивов на равенство. - Сгенерированный
hashCode()
используетArrays.hashCode(Object[])
или перегруженную версию для вычисления хеш-кода массива.
- Сгенерированный
Вывод
Все три среды IDE, описанные в этом посте (NetBeans, IntelliJ IDEA и Eclipse), генерируют звуковые реализации общих методов equals(Object)
, hashCode()
и toString()
, но между настраиваемыми этими сгенерированными методами есть различия. три IDE. Различные доступные настройки и различные сгенерированные реализации могут предоставить разработчикам, впервые знакомым с Java, уроки для изучения и рассмотрения при реализации этих методов. В то время как наиболее очевидным и значительным преимуществом способности этих IDE генерировать эти методы является экономия времени, связанное с этим автоматическим генерированием, другие преимущества генерации IDE этих методов включают способность узнавать о реализации этих методов и большую вероятность успешных реализаций. без опечаток или других ошибок.
Ссылка: | Три общих метода, сгенерированные в трех Java IDE от нашего партнера JCG Дастина Маркса в блоге Inspired by Actual Events . |