code: package mirror;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  
  @SuppressWarnings("unchecked")
  public class RefStaticMethod<T> {
      private Method method;
  
      public RefStaticMethod(Class<?> cls, Field field) throws NoSuchMethodException {
          if (field.isAnnotationPresent(MethodParams.class)) {
              Class<?>[] types = field.getAnnotation(MethodParams.class).value();
              for (int i = 0; i < types.length; i++) {
                  Class<?> clazz = types[i];
                  if (clazz.getClassLoader() == getClass().getClassLoader()) {
                      try {
                          Class.forName(clazz.getName());
                          Class<?> realClass = (Class<?>) clazz.getField("TYPE").get(null);
                          types[i] = realClass;
                      } catch (Throwable e) {
                          throw new RuntimeException(e);
                      }
                  }
              }
              this.method = cls.getDeclaredMethod(field.getName(), types);
              this.method.setAccessible(true);
          } else if (field.isAnnotationPresent(MethodReflectParams.class)) {
              boolean arrayset=false;
              String[] typeNames = field.getAnnotation(MethodReflectParams.class).value();
              Class<?>[] types = new Class<?>[typeNames.length];
              Class<?>[] types2 = new Class<?>[typeNames.length];
              for (int i = 0; i < typeNames.length; i++) {
                  Class<?> type = getProtoType(typeNames[i]);
                  if (type == null) {
                      try {
                          type = Class.forName(typeNames[i]);
                      } catch (ClassNotFoundException e) {
                          e.printStackTrace();
                      }
                  }
                  types[i] = type;
                  if("java.util.HashSet".equals(typeNames[i])){
                      arrayset=true;
                      Class<?> type2 =type;
                      try {
                          type2 = Class.forName("android.util.ArraySet");
                      } catch (ClassNotFoundException e) {
                          e.printStackTrace();
                      }
                      if(type2 != null) {
                          types2[i] = type2;
                      }else{
                          types2[i] = type;
                      }
                  }else{
                      types2[i] = type;
                  }
              }
              try {
                  this.method = cls.getDeclaredMethod(field.getName(), types);
              }catch (Exception e){
                  e.printStackTrace();
                  if(arrayset){
                      this.method = cls.getDeclaredMethod(field.getName(), types2);
                  }
              }
              this.method.setAccessible(true);
          } else {
              for (Method method : cls.getDeclaredMethods()) {
                  if (method.getName().equals(field.getName())) {
                      this.method = method;
                      this.method.setAccessible(true);
                      break;
                  }
              }
          }
  
          if (this.method == null) {
              throw new NoSuchMethodException(field.getName());
          }
      }
  
      static Class<?> getProtoType(String typeName) {
          if (typeName.equals("int")) {
              return Integer.TYPE;
          }
          if (typeName.equals("long")) {
              return Long.TYPE;
          }
          if (typeName.equals("boolean")) {
              return Boolean.TYPE;
          }
          if (typeName.equals("byte")) {
              return Byte.TYPE;
          }
          if (typeName.equals("short")) {
              return Short.TYPE;
          }
          if (typeName.equals("char")) {
              return Character.TYPE;
          }
          if (typeName.equals("float")) {
              return Float.TYPE;
          }
          if (typeName.equals("double")) {
              return Double.TYPE;
          }
          if (typeName.equals("void")) {
              return Void.TYPE;
          }
          return null;
      }
  
  
      public T call(Object... params) {
          T obj = null;
          try {
              obj = (T) method.invoke(null, params);
          } catch (Exception e) {
              e.printStackTrace();
          }
          return obj;
      }
  
      public T callWithException(Object... params) throws Throwable {
          try {
              return (T) this.method.invoke(null, params);
          } catch (InvocationTargetException e) {
              if (e.getCause() != null) {
                  throw e.getCause();
              }
              throw e;
          }
      }
  }
  