Javaで、equalsとhashCodeをオーバーライドするのが面倒くさい
※本質を逃していたので色々変えました。201201101948
Javaで、構造体のように使うクラスでは、通常equalsやhashCodeをオーバーライドするが、これが毎回同じようなコードを書かされて面倒くさい。
リフレクション(java.lang.reflect)APIを調べてみたら、これを継承で済ませられることが判明したので作った。
「同じようなコード」は、以下のブログ記事を参考にしています。
http://d.hatena.ne.jp/daira1004/20080501/1209652634
DataObject.java
import java.lang.reflect.*; public class DataObject { public boolean equals(Object o){ Class classX = this.getClass(); Class classY = o.getClass(); if(classX != classY) return false; Field[] fields = classX.getFields(); try { for(Field f : fields){ if(!f.get(this).equals(f.get(o))) return false; } } catch(IllegalAccessException e){ e.printStackTrace(); throw new Error(); } return true; } public int hashCode(){ final int m = 37; int ans = 17; for(Field f : this.getClass().getFields()){ Class t = f.getType(); int plus = 0; try { if(t == boolean.class) plus = f.getBoolean(this) ? 0 : 1; else if(t == byte.class) plus = (int)f.getByte(this); else if(t == char.class) plus = (int)f.getChar(this); else if(t == short.class) plus = (int)f.getShort(this); else if(t == int.class) plus = f.getInt(this); else if(t == long.class) { long tmp = f.getLong(this); plus = (int)(tmp ^ (tmp >>> 32)); } else if(t == float.class) plus = Float.floatToIntBits(f.getFloat(this)); else if(t == double.class){ long tmp = Double.doubleToLongBits(f.getDouble(this)); plus = (int)(tmp ^ (tmp >>> 32)); } else plus = f.get(this).hashCode(); } catch(IllegalAccessException e){ e.printStackTrace(); throw new Error(); } ans = m * ans + plus; } return ans; } }
使用側サンプル
Test.java
import java.lang.reflect.*; public class Test { public static void main(String[] args) { Hoge hoge = new Hoge(1,2); Hoge hoge2 = new Hoge(1,2); System.out.println(hoge.equals(hoge2)); //true } public static class Hoge extends DataObject { public final int a; public final int b; public Hoge(int a, int b) { this.a = a; this.b = b; } } }