In this post, I look at the differences in three "common" methods [equals(Object), hashCode(), and toString()] as generated by NetBeans 8.0.2, IntelliJ IDEA 14.0.2, and Eclipse Luna 4.4.1. The objective is not to determine which is best, but to show different approaches one can use for implementing these common methods. Along the way, some interesting insights can be picked up regarding creating of these common methods based on what the IDEs assume and prompt the developer to set.
NetBeans 8.0.2
NetBeans 8.0.2 allows the Project Properties to be configured to support the JDK 8 platform and to expect JDK 8 source formatting as shown in the next two screen snapshots.
Code is generated in NetBeans 8.0.2 by clicking on Source | Insert Code (or keystrokes Alt+Insert).
When generating the methods equals(Object)
, hashCode()
, and toString()
, NetBeans 8.0.2 asks for the attributes to be used in each of these generated methods as depicted in the next two screen snapshots.
The NetBeans-generated methods take advantage of the JDK 7-introduced Objects class.
NetBeans-Generated hashCode() Method for Class NetBeans802GeneratedCommonMethods.java@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; }NetBeans-Generated equals(Object) Method for Class NetBeans802GeneratedCommonMethods.java
@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-Generated toString() Method for Class NetBeans802GeneratedCommonMethods.java
@Override public String toString() { return "NetBeans802GeneratedCommonMethods{" + "someString=" + someString + ", timeUnit=" + timeUnit + ", integer=" + integer + ", longValue=" + longValue + '}'; }
Some observations can be made regarding the NetBeans-generated common methods:
- All generated code is automatic and does not support customization with the exception of the fields used in the methods which the operator selects.
- All of these common methods that extend counterparts in the
Object
class automatically have the@Override
annotation provided. - No Javadoc documentation is included for generated methods.
- The methods make use of the
Objects
class to make the generated code more concise with less need for null checks. - Only one format is supported for the String generated by
toString()
and that output format is a single comma-delimited line. - I did not show it in the above example, but NetBeans 8.0.2's methods generation does treat arrays differently than references, enums, and primitives in some cases:
- The generated
toString()
method treats array attributes of the instance like it treats other instance attributes: it relies on the array'stoString()
, which leads to often undesirable and typically useless results (the array's system identity hash code). It'd generally be preferable to have the string contents of array attributes provided by Arrays.toString(Object[]) or equivalent overloaded version or Arrays.deepToString(Object[]). - The generated
hashCode()
method uses Arrays.deepHashCode(Object[]) for handling arrays' hash codes. - The generated
equals(Object)
method uses Arrays.deepEquals(Object[], Object[]) for handling arrays' equality checks. - It is worth highlighting here that NetBeans uses the "deep" versions of the Arrays methods for comparing arrays for equality and computing arrays' hash codes while IntelliJ IDEA and Eclipse use the regular (not deep) versions of
Arrays
methods for comparing arrays for equality and computing arrays' hash codes.
- The generated
IntelliJ IDEA 14.0.2
For these examples, I'm using IntelliJ IDEA 14.0.2 Community Edition.
IntelliJ IDEA 14.0.2 provides the ability to configure the Project Structure to expect a "Language Level" of JDK 8.
To generate code in IntelliJ IDEA 14.0.2, one uses the Code | Generate options (or keystrokes Alt+Insert like NetBeans).
IntelliJ IDEA 14.0.2 prompts the operator for which attributes should be included in the generated methods. It also asks which fields are non-null, meaning which fields are assumed to never be null. In the snapshot shown here, they are checked, which would lead to methods not checking those attributes for null before trying to access them. In the code that I generate with IntelliJ IDEA for this post, however, I won't have those checked, meaning that IntelliJ IDEA will check for null before accessing them in the generated methods.
IntelliJ IDEA 14.0.2's toString()
generation provides a lengthy list of formats (templates) for the generated toString()
method.
IntelliJ IDEA 14.0.2 also allows the operator to select the attributes to be included in the generated toString()
method (selected when highlighted background is blue).
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-Generated hashCode() Method for Class Idea1402GeneratedCommonMethods.java
@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-Generated toString() Method for Class Idea1402GeneratedCommonMethods.java
@Override public String toString() { return "Idea1402GeneratedCommonMethods{" + "someString='" + someString + '\'' + ", timeUnit=" + timeUnit + ", integer=" + integer + ", longValue=" + longValue + '}'; }
Some observations can be made regarding the IntelliJ IDEA-generated common methods:
- Most generated code is automatic with minor available customization including the fields used in the methods which the operator selects, specification of which fields are expected to be non-null (so that null checks are not needed in generated code), and the ability to select one of eight built-in
toString()
formats. - All of these common methods that extend counterparts in the
Object
class automatically have the@Override
annotation provided. - No Javadoc documentation is included for generated methods.
- The generated methods do not make use of the
Objects
class and so require explicit checks for null for all references that could be null. - It's not shown in the above example, but IntelliJ IDEA 14.0.2 does treat arrays differently in the generation of these three common methods:
- Generated
toString()
method uses Arrays.toString(Array) on the array. - Generated
hashCode()
method uses Arrays.hashCode(Object[]) (or overloaded version) on the array. - Generated
equals(Object)
method uses Arrays.equals(Object[], Object[]) (or overloaded version) on the array.
- Generated
Eclipse Luna 4.4.1
Eclipse Luna 4.4.1 allows the Java Compiler in Project Properties to be set to JDK 8.
In Eclipse Luna, the developer uses the "Source" drop-down to select the specific type of source code generation to be performed.
Eclipse Luna allows the operator to select the attributes to be included in the common methods. It also allows the operator to specify a few characteristics of the generated methods. For example, the operator can choose to have the elements of an array printed individually in the generated toString()
method rather than an often meaningless class name and system identity hash code presented.
/* (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-Generated equals(Object) Method for Class Eclipse441GeneratedCommonMethods.java
/* (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-Generated toString() Method for Class Eclipse441GeneratedCommonMethods.java
/* (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 + "]"; }
Some observations can be made regarding the Eclipse-generated common methods:
- Eclipse provides the most points in the generation process in which the generated output can be configured. Here are some of the configurable options:
- Location in class (before or after existing methods of class) can be explicitly specified.
- All of these common methods that extend counterparts in the
Object
class automatically have the@Override
annotation provided. - "Method comments" can be generated, but they are not Javadoc style comments (use
/*
instead of/**
and explicitly state they are not Javadoc comments as part of the generated comment). - Option to "list contents of arrays instead of using native toString()" allows developer to have Arrays.toString(Array) be used (same as IntelliJ IDEA's approach and occurs if checked) or have the system identify hash code be used (same as NetBeans's approach and occurs if not checked).
- Support for four
toString()
styles plus ability to specify custom style. - Ability to limit the number of entries of an array, collection, or map that is printed in
toString()
. - Ability to use instance of in generated
equals(Object)
implementation.
- All of these common methods that extend counterparts in the
Object
class automatically have the@Override
annotation provided. - The generated methods do not make use of the
Objects
class and so require explicit checks for null for all references that could be null. - Eclipse Luna 4.4.1 does treat arrays differently when generating the three common methods highlighted in this post:
- Generated
toString()
optionally usesArrays.toString(Object[])
or overloaded version for accessing contents of array. - Generated
equals(Object)
usesArrays.equals(Object[], Object[])
or overloaded version for comparing arrays for equality. - Generated
hashCode()
usesArrays.hashCode(Object[])
or overloaded version for computing hash code of array.
- Generated
All three IDEs covered in this post (NetBeans, IntelliJ IDEA, and Eclipse) generate sound implementations of the common methods equals(Object)
, hashCode()
, and toString()
, but there are differences between the customizability of these generated methods across the three IDEs. The different customizations that are available and the different implementations that are generated can provide lessons for developers new to Java to learn about and consider when implementing these methods. While the most obvious and significant advantage of these IDEs' ability to generate these methods is the time savings associated with this automatic generation, other advantages of IDE generation of these methods include the ability to learn about implementing these methods and the greater likelihood of successful implementations without typos or other errors.
1 comment:
Thank
Post a Comment