public static List computeGetters()

in fastjson1-compatible/src/main/java/com/alibaba/fastjson/util/TypeUtils.java [679:1024]


    public static List<FieldInfo> computeGetters(Class<?> clazz, //
                                                 JSONType jsonType, //
                                                 Map<String, String> aliasMap, //
                                                 Map<String, Field> fieldCacheMap, //
                                                 boolean sorted, //
                                                 PropertyNamingStrategy propertyNamingStrategy //
    ) {
        Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<>();
        boolean kotlin = TypeUtils.isKotlin(clazz);
        // for kotlin
        Constructor[] constructors = null;
        Annotation[][] paramAnnotationArrays = null;
        String[] paramNames = null;
        short[] paramNameMapping = null;
        Method[] methods = clazz.getMethods();
        try {
            Arrays.sort(methods, new MethodInheritanceComparator());
        } catch (Throwable ignored) {
            // ignored
        }

        for (Method method : methods) {
            String methodName = method.getName();
            int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
            String label = null;
            if (Modifier.isStatic(method.getModifiers())) {
                continue;
            }

            Class<?> returnType = method.getReturnType();
            if (returnType.equals(Void.TYPE)) {
                continue;
            }

            if (method.getParameterTypes().length != 0) {
                continue;
            }

            if (returnType == ClassLoader.class
                    || returnType == InputStream.class
                    || returnType == Reader.class) {
                continue;
            }

            if ("getMetaClass".equals(methodName)
                    && "groovy.lang.MetaClass".equals(returnType.getName())) {
                continue;
            }
            if ("getSuppressed".equals(methodName)
                    && method.getDeclaringClass() == Throwable.class) {
                continue;
            }

            if (kotlin && isKotlinIgnore(clazz, methodName)) {
                continue;
            }
            /*
             *  如果在属性或者方法上存在JSONField注解,并且定制了name属性,不以类上的propertyNamingStrategy设置为准,以此字段的JSONField的name定制为准。
             */
            boolean fieldAnnotationAndNameExists = false;
            JSONField annotation = TypeUtils.getAnnotation(method, JSONField.class);
            if (annotation == null) {
                annotation = getSuperMethodAnnotation(clazz, method);
            }
            if (annotation == null && kotlin) {
                if (constructors == null) {
                    constructors = clazz.getDeclaredConstructors();
                    Constructor creatorConstructor = TypeUtils.getKotlinConstructor(constructors);
                    if (creatorConstructor != null) {
                        paramAnnotationArrays = TypeUtils.getParameterAnnotations(creatorConstructor);
                        paramNames = TypeUtils.getKoltinConstructorParameters(clazz);
                        if (paramNames != null) {
                            String[] paramNames_sorted = new String[paramNames.length];
                            System.arraycopy(paramNames, 0, paramNames_sorted, 0, paramNames.length);

                            Arrays.sort(paramNames_sorted);
                            paramNameMapping = new short[paramNames.length];
                            for (short p = 0; p < paramNames.length; p++) {
                                int index = Arrays.binarySearch(paramNames_sorted, paramNames[p]);
                                paramNameMapping[index] = p;
                            }
                            paramNames = paramNames_sorted;
                        }
                    }
                }
                if (paramNames != null && paramNameMapping != null && methodName.startsWith("get")) {
                    String propertyName = decapitalize(methodName.substring(3));
                    int p = Arrays.binarySearch(paramNames, propertyName);
                    if (p < 0) {
                        for (int i = 0; i < paramNames.length; i++) {
                            if (propertyName.equalsIgnoreCase(paramNames[i])) {
                                p = i;
                                break;
                            }
                        }
                    }
                    if (p >= 0) {
                        short index = paramNameMapping[p];
                        Annotation[] paramAnnotations = paramAnnotationArrays[index];
                        if (paramAnnotations != null) {
                            for (Annotation paramAnnotation : paramAnnotations) {
                                if (paramAnnotation instanceof JSONField) {
                                    annotation = (JSONField) paramAnnotation;
                                    break;
                                }
                            }
                        }
                        if (annotation == null) {
                            Field field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                            if (field != null) {
                                annotation = TypeUtils.getAnnotation(field, JSONField.class);
                            }
                        }
                    }
                }
            }
            if (annotation != null) {
                if (!annotation.serialize()) {
                    continue;
                }
                ordinal = annotation.ordinal();
                serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures());
                parserFeatures = Feature.of(annotation.parseFeatures());
                if (annotation.name().length() != 0) {
                    String propertyName = annotation.name();
                    if (aliasMap != null) {
                        propertyName = aliasMap.get(propertyName);
                        if (propertyName == null) {
                            continue;
                        }
                    }
                    FieldInfo fieldInfo = new FieldInfo(propertyName, method, null, clazz, null, ordinal,
                            serialzeFeatures, parserFeatures, annotation, null, label);
                    fieldInfoMap.put(propertyName, fieldInfo);
                    continue;
                }
                if (annotation.label().length() != 0) {
                    label = annotation.label();
                }
            }
            if (methodName.startsWith("get")) {
                if (methodName.length() < 4) {
                    continue;
                }
                if ("getClass".equals(methodName)) {
                    continue;
                }
                if ("getDeclaringClass".equals(methodName) && clazz.isEnum()) {
                    continue;
                }
                char c3 = methodName.charAt(3);
                String propertyName;
                Field field = null;
                if (Character.isUpperCase(c3) //
                        || c3 > 512 // for unicode method name
                ) {
                    if (compatibleWithJavaBean) {
                        propertyName = decapitalize(methodName.substring(3));
                    } else {
                        propertyName = TypeUtils.getPropertyNameByMethodName(methodName);
                    }
                    propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 3);
                } else if (c3 == '_') {
                    propertyName = methodName.substring(3);
                    field = fieldCacheMap.get(propertyName);
                    if (field == null) {
                        String temp = propertyName;
                        propertyName = methodName.substring(4);
                        field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                        if (field == null) {
                            propertyName = temp; //减少修改代码带来的影响
                        }
                    }
                } else if (c3 == 'f') {
                    propertyName = methodName.substring(3);
                } else if (methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))) {
                    propertyName = decapitalize(methodName.substring(3));
                } else {
                    propertyName = methodName.substring(3);
                    field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                    if (field == null) {
                        continue;
                    }
                }
                boolean ignore = isJSONTypeIgnore(clazz, propertyName);
                if (ignore) {
                    continue;
                }

                if (field == null) {
                    // 假如bean的field很多的情况一下,轮询时将大大降低效率
                    field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                }

                if (field == null && propertyName.length() > 1) {
                    char ch = propertyName.charAt(1);
                    if (ch >= 'A' && ch <= 'Z') {
                        String javaBeanCompatiblePropertyName = decapitalize(methodName.substring(3));
                        field = ParserConfig.getFieldFromCache(javaBeanCompatiblePropertyName, fieldCacheMap);
                    }
                }
                JSONField fieldAnnotation = null;
                if (field != null) {
                    fieldAnnotation = TypeUtils.getAnnotation(field, JSONField.class);
                    if (fieldAnnotation != null) {
                        if (!fieldAnnotation.serialize()) {
                            continue;
                        }
                        ordinal = fieldAnnotation.ordinal();
                        serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                        parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                        if (fieldAnnotation.name().length() != 0) {
                            fieldAnnotationAndNameExists = true;
                            propertyName = fieldAnnotation.name();
                            if (aliasMap != null) {
                                propertyName = aliasMap.get(propertyName);
                                if (propertyName == null) {
                                    continue;
                                }
                            }
                        }
                        if (fieldAnnotation.label().length() != 0) {
                            label = fieldAnnotation.label();
                        }
                    }
                }
                if (aliasMap != null) {
                    propertyName = aliasMap.get(propertyName);
                    if (propertyName == null) {
                        continue;
                    }
                }
                if (propertyNamingStrategy != null && !fieldAnnotationAndNameExists) {
                    propertyName = propertyNamingStrategy.translate(propertyName);
                }
                FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
                        annotation, fieldAnnotation, label);
                fieldInfoMap.put(propertyName, fieldInfo);
            }
            if (methodName.startsWith("is")) {
                if (methodName.length() < 3) {
                    continue;
                }
                if (returnType != Boolean.TYPE
                        && returnType != Boolean.class) {
                    continue;
                }
                char c2 = methodName.charAt(2);
                String propertyName;
                Field field = null;
                if (Character.isUpperCase(c2)) {
                    if (compatibleWithJavaBean) {
                        propertyName = decapitalize(methodName.substring(2));
                    } else {
                        propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
                    }
                    propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 2);
                } else if (c2 == '_') {
                    propertyName = methodName.substring(3);
                    field = fieldCacheMap.get(propertyName);
                    if (field == null) {
                        String temp = propertyName;
                        propertyName = methodName.substring(2);
                        field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                        if (field == null) {
                            propertyName = temp;
                        }
                    }
                } else if (c2 == 'f') {
                    propertyName = methodName.substring(2);
                } else {
                    propertyName = methodName.substring(2);
                    field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                    if (field == null) {
                        continue;
                    }
                }
                boolean ignore = isJSONTypeIgnore(clazz, propertyName);
                if (ignore) {
                    continue;
                }

                if (field == null) {
                    field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                }

                if (field == null) {
                    field = ParserConfig.getFieldFromCache(methodName, fieldCacheMap);
                }
                JSONField fieldAnnotation = null;
                if (field != null) {
                    fieldAnnotation = TypeUtils.getAnnotation(field, JSONField.class);
                    if (fieldAnnotation != null) {
                        if (!fieldAnnotation.serialize()) {
                            continue;
                        }
                        ordinal = fieldAnnotation.ordinal();
                        serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                        parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                        if (fieldAnnotation.name().length() != 0) {
                            propertyName = fieldAnnotation.name();
                            if (aliasMap != null) {
                                propertyName = aliasMap.get(propertyName);
                                if (propertyName == null) {
                                    continue;
                                }
                            }
                        }
                        if (fieldAnnotation.label().length() != 0) {
                            label = fieldAnnotation.label();
                        }
                    }
                }
                if (aliasMap != null) {
                    propertyName = aliasMap.get(propertyName);
                    if (propertyName == null) {
                        continue;
                    }
                }
                if (propertyNamingStrategy != null) {
                    propertyName = propertyNamingStrategy.translate(propertyName);
                }
                //优先选择get
                if (fieldInfoMap.containsKey(propertyName)) {
                    continue;
                }
                FieldInfo fieldInfo = new FieldInfo(
                        propertyName,
                        method,
                        field,
                        clazz,
                        null,
                        ordinal,
                        serialzeFeatures,
                        parserFeatures,
                        annotation,
                        fieldAnnotation,
                        label
                );
                fieldInfoMap.put(propertyName, fieldInfo);
            }
        }
        Field[] fields = clazz.getFields();
        computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);
        return getFieldInfos(clazz, sorted, fieldInfoMap);
    }