Java reflection: array of classes vs. array of par

2019-08-02 02:40发布

问题:

I have an object m of class Method. I invoked m.getParameterTypes() to create an array params of the method's parameters.

I also have an array arr of Objects. I wanted to check if the objects in arr are of the same types as the types in params (and in the same order).

What I did was to create an array classes which includes the class of each object in arr. Then I tried to compare classes with params. Turns out they can never be equal because the classes in the classes array are in the format of java.lang.String and the parameters in the param array are in the format of String. How can I compare the arrays? How can I change the format of one of them?

回答1:

getParameterTypes() returns a Class<?>[] whereas the actual arguments themselves will be objects (so you'll have an Object[]). To check that the arguments are valid, you could use:

if (parameterTypes.length != arr.length) {
  // Invalid: wrong number of arguments
}

for (int i=0; i < parameterTypes.length; i++) {
  if (arr[i] == null && parameterTypes[i].isPrimitive()) {
    // Invalid: can't pass null for a primitive parameter
  } else if (arr[i] != null && !parameterTypes[i].isInstance(arr[i])) {
     // Invalid: invalid argument type
  } else {
     // Valid
  }
}

(Do whatever you need to do for the valid/invalid cases, of course.)



回答2:

Instead of you checking if the method's parameters are compatible with your Object array, why not let Class.getMethod() do it for you? What I mean is, why not do something like this:

Class[] classes = new Class[myArr.length];
for (int i=0; i<myArr.length; i++) {
    classes[i] = myArr[i].getClass();
}

Method m = YouMethodsClass.class.getMethod("methodName", classes);

Wouldn't that work for you?



回答3:

If you are doing this sort of comparison you should use the fully qualified name ('java.lang.String' type) to ensure the match is really correct (since two classes can have the same "simple" name and be from different packages).

Can you provide the code you used, so we can guide you on what needs to be changed to obtain the fully qualified names?

Method getParameterTypes() returns a Class[], so each element is a Class. You can call either getCanonicalName() (or getName() in some circumstances, see the javadoc for Class) to get the fully qualified name.

For the array of objects, you can call object.getClass().getCanonicalName() to get the equivalent.

EDIT: Jon Skeet's reply is a better approach where you don't compare names at all, but instead use the Class isInstance() method to check that the Class is compatible.