public static void getters()

in core/src/main/java/com/alibaba/fastjson2/util/BeanUtils.java [924:1131]


    public static void getters(Class objectClass, Class mixinSource, boolean kotlin, Consumer<Method> methodConsumer) {
        if (objectClass == null) {
            return;
        }

        if (Proxy.isProxyClass(objectClass)) {
            Class[] interfaces = objectClass.getInterfaces();
            if (interfaces.length == 1) {
                getters(interfaces[0], methodConsumer);
                return;
            }
        }

        if (ignore(objectClass)) {
            return;
        }

        Class superClass = objectClass.getSuperclass();
        if (TypeUtils.isProxy(objectClass)) {
            getters(superClass, methodConsumer);
            return;
        }

        boolean record = isRecord(objectClass);
        boolean jdbcStruct = JdbcSupport.isStruct(objectClass);

        String[] recordFieldNames = null;
        if (record) {
            recordFieldNames = getRecordFieldNames(objectClass);
        }

        Method[] methods = methodCache.get(objectClass);
        if (methods == null) {
            methods = getMethods(objectClass);
            methodCache.putIfAbsent(objectClass, methods);
        }

        boolean protobufMessageV3 = superClass != null && "com.google.protobuf.GeneratedMessageV3".equals(superClass.getName());

        for (Method method : methods) {
            int paramType = method.getParameterCount();
            if (paramType != 0) {
                continue;
            }

            int mods = method.getModifiers();
            if (Modifier.isStatic(mods)) {
                continue;
            }

            Class<?> returnClass = method.getReturnType();
            if (returnClass == Void.class || returnClass == void.class || ignore(returnClass)) {
                continue;
            }

            Class<?> declaringClass = method.getDeclaringClass();
            if (declaringClass == Enum.class || declaringClass == Object.class) {
                continue;
            }

            String methodName = method.getName();
            if (jdbcStruct) {
                if (!"getSQLTypeName".equals(methodName) && !"getAttributes".equals(methodName)) {
                    continue;
                }
            }

            boolean methodSkip = false;
            switch (methodName) {
                case "isInitialized":
                case "getInitializationErrorString":
                case "getSerializedSize":
                    if (protobufMessageV3) {
                        methodSkip = true;
                    }
                    break;
                case "equals":
                case "hashCode":
                case "toString":
                    methodSkip = true;
                    break;
                default:
                    break;
            }

            if (methodSkip) {
                continue;
            }

            if (protobufMessageV3) {
                if ((methodName.endsWith("Type") || methodName.endsWith("Bytes"))
                        && "com.google.protobuf.ByteString".equals(returnClass.getName())) {
                    continue;
                }
            }

            // skip thrift isSetXXX
            if (methodName.startsWith("isSet") && returnClass == boolean.class) {
                boolean setterFound = false, unsetFound = false, getterFound = false;
                String setterName = BeanUtils.getterName(methodName, null);
                String getterName = "g" + setterName.substring(1);

                String unsetName = "un" + setterName;
                for (Method m : methods) {
                    if (m.getName().equals(setterName)
                            && m.getParameterCount() == 1
                            && m.getReturnType() == void.class) {
                        setterFound = true;
                    } else if (m.getName().equals(getterName)
                            && m.getParameterCount() == 0) {
                        getterFound = true;
                    } else if (m.getName().equals(unsetName)
                            && m.getParameterCount() == 0
                            && m.getReturnType() == void.class) {
                        unsetFound = true;
                    }
                }

                if (setterFound && unsetFound && getterFound
                        && findAnnotation(method, JSONField.class) == null) {
                    continue;
                }
            }

            if (record) {
                boolean match = false;
                for (String recordFieldName : recordFieldNames) {
                    if (methodName.equals(recordFieldName)) {
                        match = true;
                        break;
                    }
                }

                if (match) {
                    methodConsumer.accept(method);
                    continue;
                }
            }

            final int methodNameLength = methodName.length();
            boolean nameMatch = methodNameLength > 3 && methodName.startsWith("get");
            if (nameMatch) {
                char firstChar = methodName.charAt(3);
                if (firstChar >= 'a' && firstChar <= 'z' && methodNameLength == 4) {
                    nameMatch = false;
                }
            } else if (returnClass == boolean.class || returnClass == Boolean.class || kotlin) {
                nameMatch = methodNameLength > 2 && methodName.startsWith("is");
                if (nameMatch) {
                    char firstChar = methodName.charAt(2);
                    if (firstChar >= 'a' && firstChar <= 'z' && methodNameLength == 3) {
                        nameMatch = false;
                    }
                }
            }

            if (!nameMatch) {
                if (isJSONField(method)) {
                    nameMatch = true;
                }
            }

            if (!nameMatch && mixinSource != null) {
                Method mixinMethod = getMethod(mixinSource, method);
                if (mixinMethod != null) {
                    if (isJSONField(mixinMethod)) {
                        nameMatch = true;
                    }
                }
            }

            if (!nameMatch
                    && objectClass != returnClass
                    && (!methodName.startsWith("build"))
                    && fluentSetter(objectClass, methodName, returnClass) != null) {
                nameMatch = true;
            }

            if (!nameMatch) {
                continue;
            }

            if (protobufMessageV3) {
                if (method.getDeclaringClass() == superClass) {
                    continue;
                }
                Class<?> returnType = method.getReturnType();
                boolean ignore = false;
                switch (methodName) {
                    case "getUnknownFields":
                    case "getSerializedSize":
                    case "getParserForType":
                    case "getMessageBytes":
                    case "getDefaultInstanceForType":
                        ignore = returnType.getName().startsWith("com.google.protobuf.") || returnType == objectClass;
                        break;
                    default:
                        break;
                }

                if (ignore) {
                    continue;
                }
            }

            methodConsumer.accept(method);
        }
    }