背景
開發過程中發現一個問題,項目中用Set保存AopMethod對象用於去重,但是發現即使往set中添加相同內容的對象,每次也能夠添加成功。
AopMethod類的部分代碼如下:
public class AopMethod { private String methodName; private Class<?>[] parameterTypes = new Class<?>[]{}; //是否需要忽略掉參數匹配 private boolean ignoreParameterTypes; public AopMethod() { } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AopMethod aopMethod = (AopMethod) o; return ignoreParameterTypes == aopMethod.ignoreParameterTypes && Objects.equals(methodName, aopMethod.methodName) && Arrays.equals(parameterTypes, aopMethod.parameterTypes); } @Override public int hashCode() { return Objects.hash(methodName, parameterTypes, ignoreParameterTypes); } }
通過debug發現,對象即使內容完全相同,hashCode每次返回的hash值都是不一樣的。
AopMethod{methodName='m81', parameterTypes=[int], ignoreParameterTypes=false} hash:-1850752941
AopMethod{methodName='m81', parameterTypes=[int], ignoreParameterTypes=false} hash:-526785805
equals、hashCode方法是Idea IDE自動生成的,看來,自動生成的不靠譜啊。。。
why
Class<?>[] parameterTypes = new Class<?>[]{};
Objects.hash內部會調用hahCode方法,但是parameterTypes為數組,而數組是沒有hashCode()方法的。
最佳實踐
不要依賴Idea IDE自動生成的hashCode方法。
如果有數組的話,用數組用Arrays.hashCode()包起來,然后再作為Objects.hash()方法的參數。
hashCode改成下面的實現就OK了!
@Override public int hashCode() { return Objects.hash(methodName, Arrays.hashCode(parameterTypes), ignoreParameterTypes); }
