title: Overriding hashCode when using isAssignableFrom on equals method
body: <p>I need to find a way to cache Methods(<code>java.lang.reflect.Method</code>) in such a way that whenever I call a function with the class (<code>Class</code>) methodName(<code>String</code>) and arguments(<code>T[]</code>) the function will return the cached method if exists or find the method, add it to the cache and return it.</p>
  
  <p>I want to use HashMap for caching so I can find the method in O(1) but the problem is that I need to use<code>isAssignableFrom</code> when I override the equals method: </p>
  
  <pre><code>public class A1 extends AParent {}
  
  public class A2 extends AParent {}
  
  public class AParent {}
  
  public class Temp{
      public void testFunc(AParent a){}
  }
  </code></pre>
  
  <p>This is the class I use for the keys in the HashMap : </p>
  
  <pre><code>import java.util.Arrays;
  
  class MethodAbs{
  Class c;
  String methodName;
  Class&lt;?&gt;[] argsTypes;
  
  public MethodAbs(Class c, String methodName, Class&lt;?&gt;[] argsTypes){
      this.c = c;
      this.methodName = methodName;
      this.argsTypes = argsTypes;
  }
  
  @Override
  public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
  
      MethodAbs methodAbs = (MethodAbs) o;
  
      if (c != null ? !c.equals(methodAbs.c) : methodAbs.c != null) return false;
      if (methodName != null ? !methodName.equals(methodAbs.methodName) : methodAbs.methodName != null)
          return false;
      return isArgsTypesEq(argsTypes, methodAbs.argsTypes);
  
  }
  
  //a method is equals to the one cached if the arguments types
  // can be cast to the ones that are saved on the map,
  // i.e the ones on the method declaration 
  
  private boolean isArgsTypesEq(Class&lt;?&gt;[] at1, Class&lt;?&gt;[] at2){
      boolean res = at1.length == at2.length;
      for(int i = 0; i&lt;at1.length &amp;&amp; res; i++){
          if(!at1[i].isAssignableFrom(at2[i])) res = false;
      }
      return res;
  }
  
  
  //default implementation (not working properly!)
  
  @Override
  public int hashCode() {
      int result = c != null ? c.hashCode() : 0;
      result = 31 * result + (methodName != null ? methodName.hashCode() : 0);
      result = 31 * result + Arrays.hashCode(argsTypes);
      return result;
  }
  
  
  }
  </code></pre>
  
  <p>The class I use for caching </p>
  
  <pre><code>class Run{
  
  public Map&lt;MethodAbs, Method&gt; map = new HashMap&lt;&gt;();
  
  public&lt;T&gt; Method myFunc(Class c, String methodName, T[] args){
      MethodAbs ma = new MethodAbs(c, methodName, getTypes(args));
      if(map.containsKey(ma)){
          return map.get(ma);
      }
      else{
          for(Method method: c.getMethods()){
              MethodAbs currMethodAbs = new MethodAbs(c, method.getName(), method.getParameterTypes());
              if(!map.containsKey(currMethodAbs))
                  map.put(currMethodAbs, method);
              if(currMethodAbs.equals(ma)) break;
          }
      }
      return map.get(ma);
  }
  
  private&lt;T&gt; Class&lt;?&gt;[] getTypes(T[] args) {
      Class&lt;?&gt;[] types = new Class&lt;?&gt;[args.length];
      for(int i = 0; i&lt; args.length; i++){
          types[i] = args[i].getClass();
      }
      return types;
  }
  }
  </code></pre>
  
  <p>And Main: </p>
  
  <pre><code> public static void main(String[] args){
      Run r = new Run();
      Object [] arr = new Object[1];
      arr[0] = new A1();
      r.myFunc(Temp.class, "testFunc", arr);
      arr[0] = new A2();
      r.myFunc(Temp.class, "testFunc", arr);
  
  }
  </code></pre>
  
  <p>In the scenario above after calling r.myFunc for the first time, the map looks like this: </p>
  
  <pre><code>MethodAbs(Temp.class, "testFunc", [AParent.class]) 
  </code></pre>
  
  <p>on the second time map.containsKey will return false(because AParent.hashCode != A2.hashCode) but they are <code>equals</code>.</p>
  
  <ul>
  <li>The hierarchy shown in the example will not necessarily look like that(for example A2 can be a grandchild of AParent) </li>
  </ul>
  
  <p>I know I can use the Class and method name as keys and the value will be a list of methods which I'll need to iterate and compare with equals but I'm trying to find a better way... </p>