sourcecode generation of good equals, hashCode and toString
* 7/22: pardon the bad formatting on the code samples. i'm working on fixing things up...
i've tried several of the popular plugins for automatically creating implementations of hashCode, equals and toString in Java and have thus far found all wanting in one way or another. being ever pleased with code that writes code, i rolled my own years ago based on the detailed directives in Josh Bloch's "Effective Java" and based on the very strict JavaSoft-based coding standard i had become accustomed to while working alongside some very good practitioners.
have always thought about making my own plugin but have yet to get to it. instead dusted this utility off every so often over what has now become an amazing number of years. time really does fly! may yet roll a plugin for grins, but do not do near as much coding as i'd like these days.
so, given the following example of code for which you might want to spin up "perfect" hashCode, equals and hashCode implementations...
...the utility will generate the following:
in current times of annotations, and perhaps with better plugins for doing so now available, this utility may not be worth the trouble. i'll look into it, modernizing it if nothing else. the utility code:
i've tried several of the popular plugins for automatically creating implementations of hashCode, equals and toString in Java and have thus far found all wanting in one way or another. being ever pleased with code that writes code, i rolled my own years ago based on the detailed directives in Josh Bloch's "Effective Java" and based on the very strict JavaSoft-based coding standard i had become accustomed to while working alongside some very good practitioners.
have always thought about making my own plugin but have yet to get to it. instead dusted this utility off every so often over what has now become an amazing number of years. time really does fly! may yet roll a plugin for grins, but do not do near as much coding as i'd like these days.
so, given the following example of code for which you might want to spin up "perfect" hashCode, equals and hashCode implementations...
public class TempBean {
private String _foo;
private String[] _bar;
private TempBean _miniMe;
private int _littleI;
private Double _double;
}
...the utility will generate the following:
/**
* Compares this object to the specified object. The result is
*trueif and only if the argument is notnull
* and is an instance ofTempBeanwhich represents a
* value equivalent to thisTempBean.
*
* @param object the object to compare with.
* @returntrueif the objects are the same,
* returnsfalseotherwise.
*/
public boolean equals(Object object) {
if (object != this) {
if (object != null && getClass().equals(object.getClass())) {
final TempBean other = (TempBean) object;
return (_foo == null ? other._foo == null : _foo.equals(other._foo)) &&
(_bar == null ? other._bar == null : _bar.equals(other._bar)) &&
(_miniMe == null ? other._miniMe == null : _miniMe.equals(other._miniMe)) &&
(_littleI == other._littleI) &&
(_double == null ? other._double == null : _double.equals(other._double));
}
return false;
}
return true;
}
/**
* Returns a hash code value for thisTempBean.
*
* @return a hash code value for thisTempBean.
*/
public int hashCode() {
int hashCode = -1246173291; // result of getClass().getName().hashCode()
hashCode = 37 * hashCode + (_foo == null ? 0 : _foo.hashCode());
for (int i = 0; i < hashcode =" 37" hashcode =" 37" _minime ="=" hashcode =" 37" hashcode =" 37" _double ="=">String representation of thisTempBean.
*/
public String toString() {
StringBuffer buffer = new StringBuffer("TempBean(");
buffer.append("_foo=" + _foo + ",");
buffer.append("_bar=" + _bar + ",");
buffer.append("_miniMe=" + _miniMe + ",");
buffer.append("_littleI=" + _littleI + ",");
buffer.append("_double=" + _double + ")");
return buffer.toString();
}
in current times of annotations, and perhaps with better plugins for doing so now available, this utility may not be worth the trouble. i'll look into it, modernizing it if nothing else. the utility code:
package com.erickreid.temp;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/**
* A utility class that generates source code for good
*boolean equals(),int hashCode(), and
*String toString()implementations.
*
*
* The algorithms used here are based largely on those presented in
* "Effective Java" by
* Josh Bloch, with some variations based on conversations with colleagues.
*
*
* @author Erick G. Reid
*/
public class SourcecodeGenerator {
/**
* Returns aStringrepresenting usable
*boolean equals(Object)sourcecode for the given
*Class.
*
* @param source theClassto inspect.
* @return aStringrepresenting usable
*boolean equals(Object)sourcecode for the given
*Class.
*/
public static String getEqualsSourceCode(Class source) {
Field[] fields = _getEligibleFields(source);
StringBuffer sb = new StringBuffer();
String className = _getClassName(source);
sb.append("/**\n");
sb.append(" * Compares this object to the specified object. The result is\n");
sb.append(" *trueif and only if the argument is notnull\n");
sb.append(" * and is an instance of" + className + "which represents a\n");
sb.append(" * value equivalent to this" + className + ".\n");
sb.append(" *\n");
sb.append(" * @param object the object to compare with.\n");
sb.append(" * @returntrueif the objects are the same,\n");
sb.append(" * returnsfalseotherwise.\n");
sb.append(" */\n");
sb.append("public boolean equals(Object object) {\n");
sb.append(" if (object != this) {\n");
if (fields.length == 0) {
sb.append(
" return object != null && getClass().equals(object.getClass());\n");
}
else {
sb.append(" if (object != null && getClass().equals(object.getClass())) {\n");
sb.append(" final " + className + " other = (" + className + ") object;\n");
for (int i = 0; i < i ="=" i ="=">String representing usablehashCode()
* sourcecode for the givenClass.
*
* @param source theClassto inspect.
* @return aStringrepresenting usablehashCode()
* sourcecode for the givenClass.
*/
public static String getHashCodeSourceCode(Class source) {
Field[] fields = _getEligibleFields(source);
String className = _getClassName(source);
StringBuffer sb = new StringBuffer();
sb.append("/**\n");
sb.append(" * Returns a hash code value for this" +.\n");
className + "
sb.append(" *\n");
sb.append(" * @return a hash code value for this" +.\n");
className + "
sb.append(" */\n");
sb.append("public int hashCode() {\n");
sb.append(" int hashCode = " + source.getName().hashCode() +
"; // result of getClass().getName().hashCode() \n");
for (int i = 0; i < i =" 0;">String representing usable
*String toString()sourcecode for the givenClass.
*
* @param source theClassto inspect.
* @return aStringrepresenting usable
*String toString()sourcecode for the given
*Class.
*/
public static String getToStringSourceCode(Class source) {
Field[] fields = _getEligibleFields(source);
StringBuffer sb = new StringBuffer();
String className = _getClassName(source);
sb.append("/**\n");
sb.append(" * Returns aStringrepresentation of this" +.\n");
className + "
sb.append(" *\n");
sb.append(" * @return aStringrepresentation of this" +.\n");
className + "
sb.append(" */\n");
sb.append("public String toString() {\n");
if (fields.length == 0) {
sb.append(" return \"" + className + "()\";\n");
}
else {
sb.append(" StringBuffer buffer = new StringBuffer(\"" +
className + "(\");\n");
for (int i = 0; i < i ="=" hashcode =" 37" hashcode =" 37" hashcode =" 37">>> 32));\n");
}
else if (Float.TYPE.equals(type)) {
sb.append(indent + "hashCode = 37 * hashCode + Float.floatToIntBits(" +
fieldName + ");\n");
}
else if (Double.TYPE.equals(type)) {
sb.append(indent + "long longBits = Double.doubleToLongBits(" +
fieldName + ");\n");
sb.append(indent +
"hashCode = 37 * hashCode + (int)(longBits ^ (longBits >>> 32));\n");
}
return;
}
sb.append(indent + "hashCode = 37 * hashCode + (" +
fieldName + " == null ? 0 : " + fieldName + ".hashCode());\n");
}
/**
* Returns all instance fields from the given class that are found to be
* non-public.
*/
private static Field[] _getEligibleFields(Class source) {
Field[] fields = source.getDeclaredFields();
ListeligibleFields = new ArrayList ();
for (int i = 0; i < modifiers =" fields[i].getModifiers();" classname =" source.getName();">

0 Comments:
Post a Comment
<< Home