Статьи

Три распространенных метода, сгенерированные в трех Java IDE

В этой статье я рассмотрю различия в трех «общих» методах [ equals (Object) , hashCode () и toString () ], сгенерированных NetBeans 8.0.2 , IntelliJ IDEA 14.0.2 и Eclipse Luna 4.4.1 , Цель состоит не в том, чтобы определить, что лучше, а в том, чтобы показать различные подходы, которые можно использовать для реализации этих общих методов. По пути, некоторые интересные идеи могут быть получены относительно создания этих общих методов, основанных на том, что IDE предполагают и побуждают разработчика устанавливать.

NetBeans 8.0.2

netbeans802

NetBeans 8.0.2 позволяет настроить свойства проекта для поддержки платформы JDK 8 и ожидать форматирования источника JDK 8, как показано на следующих двух снимках экрана.

netbeans802_projectProperties_Libraries_JavaPlatform8

netbeans802_projectProperties_Sources_sourceFormat8

Код генерируется в NetBeans 8.0.2, нажав Source | Вставить код (или сочетание клавиш Alt + Insert).

netbeans802_source_insertCode_altInsert

При создании методов equals(Object) , hashCode() и toString() NetBeans 8.0.2 запрашивает атрибуты, которые будут использоваться в каждом из этих сгенерированных методов, как показано на следующих двух снимках экрана.

netbeans802_generateEqualsAndHashCode

netbeans802_generateToString

Методы, сгенерированные 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 .

idea_1402

IntelliJ IDEA 14.0.2 предоставляет возможность настроить структуру проекта так, чтобы он ожидал «языковой уровень» JDK 8.

idea14_ProjectStructure_LanguageLevel_8

Для генерации кода в IntelliJ IDEA 14.0.2 используется код | Создайте параметры (или клавиши Alt + Insert, как NetBeans).

idea14_codeGenerateAltInsert

IntelliJ IDEA 14.0.2 запрашивает оператор, для которого атрибуты должны быть включены в сгенерированные методы. Он также спрашивает, какие поля не являются нулевыми, означая, что поля, как предполагается, никогда не будут нулевыми. На снимке, показанном здесь, они проверяются, что приводит к тому, что методы не проверяют эти атрибуты на null, прежде чем пытаться получить к ним доступ. Однако в коде, который я сгенерирую с помощью IntelliJ IDEA для этого поста, я не проверю их, а это означает, что IntelliJ IDEA будет проверять наличие нуля, прежде чем обращаться к ним в сгенерированных методах.

idea14_codeGenerateEqualsAndHashCode_Equals

idea14_codeGenerateEqualsAndHashCode_HashCode

idea14_codeGenerateEqualsAndHashCode_NotNull

Генерация toString() IntelliJ IDEA 14.0.2 предоставляет длинный список форматов (шаблонов) для сгенерированного метода toString() .

idea14_codeGenerateToStringTemplateOptions

IntelliJ IDEA 14.0.2 также позволяет оператору выбирать атрибуты, которые будут включены в сгенерированный метод toString() (выбирается, когда выделенный фон имеет синий цвет).

idea14_codeGenerateToStringHighlightedAttributesBlueBackground

Генерируемый 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

eclipseLuna441

Eclipse Luna 4.4.1 позволяет установить для компилятора Java в свойствах проекта значение JDK 8.

eclipse441_ProjectProperties_JavaCompiler

В Eclipse Luna разработчик использует раскрывающийся список «Источник», чтобы выбрать конкретный тип генерации исходного кода, который необходимо выполнить.

eclipse441_Source_GenerateHashCodeAndEquals

Eclipse Luna позволяет оператору выбирать атрибуты, которые будут включены в общие методы. Это также позволяет оператору указать несколько характеристик генерируемых методов. Например, оператор может выбрать, чтобы элементы массива печатались индивидуально в сгенерированном методе toString() а не представляли часто бессмысленное имя класса и системный идентификатор хеш-кода.

eclipse441_GenerateHashCodeEquals

eclipse441_GenerateToString

Генерируемый 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 этих методов включают способность узнавать о реализации этих методов и большую вероятность успешных реализаций. без опечаток или других ошибок.