ClassCastException While casting List to C

2019-03-31 01:42发布

问题:

I have a method which has a list of inputs and each input value I have to cast it to required type. (Actually this list has values of parameters in "some" form which I am supposed to converted into required type, the required type is the type which method requires, this is for api invocation through reflection)

I have written code like this:

Type[] argTypes = method.getGenericParameterTypes();
List<Object> acutalValues = // List of actual values from method input.
// Resultant list of arguments which will holds casted values.
List<Object> arguments = new ArrayList<Object>(argTypes.length);

for (int i = 0; i < argTypes.length; i++) {
 Class<?> requiredClassTYpe = (Class<?>) argTypes[i]; // argTypes[1] =java.util.List<java.lang.String> fails..
 // cast the actual value to the required type. Required type is requiredClassType
 arguments.add(castToRequiredType(requiredClassTYpe, actualValues.get(i)));
 }

The exception message is like this :

ClassCastException: Cannot cast sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl (id=77) to java.lang.Class

Now if I change the first line to

Type[] argTypes = method.getParameterTypes()

Then it passes any idea why it might be happening like this?

回答1:

Because as stated in method.getGenericParameterTypes() JavaDoc it:

returns an array of Type objects that represent the formal parameter types

...

If a formal parameter type is a parameterized type, the Type object returned for it must accurately reflect the actual type parameters used in the source code.

Thus if your method declaration looks like:

public void myMethod(String string, List<String> list) { ... }

argTypes[0] will contain instance of Class (i.e. Class<? extends String>), but argTypes[1] will contain instance of java.lang.reflect.ParameterizedType. You can get information about actual type arguments of ParameterizedType using getActualTypeArguments() method. Example for case I described above:

Type[] listTypeArgs = ((ParameterizedType) argTypes[1]).getActualTypeArguments()

// listTypeArgs.length == 1 as List<String> have one type argument
// listTypeArgs[0] now contains instance of Class<? extends String>


回答2:

Since your method argument is a parameterized collection type, getGenericParameterTypes returns a ParameterizedType, not a Type. To get the actual type, you need to first check whether each element of argTypes is an instance of ParameterizedType, and if it is call ParameterizedType.getActualTypeArguments().

Having said that, I can't tell what your code is trying to do. Your result object is still a List<Object>, so you are still going to have to cast the elements to their correct type when you get them from the list. Casting the elements before storing them in the list doesn't accomplish anything.



回答3:

Type[] argTypes = method.getParamterTypes()

I believe you are missing an "e" in your method call, should be getParameterTypes()