private static Type canonicalize(Class<?> thisClass,
                                     ParameterizedType type,
                                     Type[] actualTypeArguments,
                                     int actualIndex) {
        Type rawType = type.getRawType();
        Type[] argTypes = type.getActualTypeArguments();

        for (int i = 0; i < argTypes.length; ++i) {
            if (argTypes[i] instanceof TypeVariable
                    && actualIndex < actualTypeArguments.length) {
                argTypes[i] = actualTypeArguments[actualIndex++];
            }

            // fix for openjdk and android env
            if (argTypes[i] instanceof GenericArrayType) {
                Type componentType = argTypes[i];

                int dimension = 0;
                while (componentType instanceof GenericArrayType) {
                    dimension++;
                    componentType = ((GenericArrayType) componentType).getGenericComponentType();
                }

                if (componentType instanceof Class<?>) {
                    Class<?> cls = (Class<?>) componentType;
                    Loader:
                    if (cls.isPrimitive()) {
                        final char ch;
                        if (cls == int.class) {
                            ch = 'I';
                        } else if (cls == long.class) {
                            ch = 'J';
                        } else if (cls == float.class) {
                            ch = 'F';
                        } else if (cls == double.class) {
                            ch = 'D';
                        } else if (cls == boolean.class) {
                            ch = 'Z';
                        } else if (cls == char.class) {
                            ch = 'C';
                        } else if (cls == byte.class) {
                            ch = 'B';
                        } else if (cls == short.class) {
                            ch = 'S';
                        } else {
                            break Loader;
                        }

                        char[] chars = new char[dimension + 1];
                        for (int j = 0; j < dimension; j++) {
                            chars[j] = '[';
                        }
                        chars[dimension] = ch;
                        String typeName = new String(chars);
                        argTypes[i] = TypeUtils.loadClass(typeName);
                    }
                }
            }

            // if it is a ParameterizedType,
            // iterate to find the real Type
            if (argTypes[i] instanceof ParameterizedType) {
                argTypes[i] = canonicalize(
                        thisClass, (ParameterizedType) argTypes[i],
                        actualTypeArguments, actualIndex
                );
            }
        }

        return new ParameterizedTypeImpl(
                argTypes, thisClass, rawType
        );
    }
@param thisClass this class
@param type the parameterizedType
@param actualTypeArguments an array of Type objects representing the actual type arguments to this type
@param actualIndex the actual index
@since 2.0.3
core/src/main/java/com/alibaba/fastjson2/TypeReference.java