java用反射的方式根据字段1处理字段2

概述

传入一个列表,然后根据精度的字段,处理汇率值的字段。进行补零。
传入的列表类型是不定的,所以设定成一个泛型方法。
工具类是通过反射获取属性值和设置属性值来完成对汇率值的处理的。在类中定义了内部的 ExchangeRateFieldHandler 类,在处理汇率值时直接使用该类即可,而不用担心通用性问题。

代码

package xxx;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * 对汇率值进行处理的工具类
 * @author xxx
 * @since 2023/7/4 11:37
 */
@Slf4j
public class ExchangeRateUtils {

    /**
     * 工具类不应该被实例化
     */
    private ExchangeRateUtils() {
        throw new AssertionError();
    }

    /**
     * 用于处理精度和值属性的通用工具类。
     * @param  要处理的对象类型
     */
    public static class ExchangeRateFieldHandler<T> {

        /**
         * 检查列表中的汇率值是否处理成功。
         * @param list 要检查的列表
         * @param precisionPropertyName 精度属性名称
         * @param valuePropertyName 值属性名称
         * @return 返回仍存在科学计数法表示或仍存在精度不足尚未补零的汇率的数量
         * @throws NoSuchMethodException 如果指定的方法不存在时抛出此异常
         * @throws InvocationTargetException 在执行目标方法失败时抛出此异常
         * @throws IllegalAccessException 在访问方法时发生非法访问时抛出此异常
         */
        public int checkExchangeRateValue(List<T> list, String precisionPropertyName, String valuePropertyName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException{
            if (list == null || list.isEmpty()) {
                throw new IllegalArgumentException("列表不能为null或空");
            }
            List<T> res = new ArrayList<>();
            for (T item : list) {
                String precision = (String) getProperty(item, precisionPropertyName);
                String value = (String) getProperty(item, valuePropertyName);
                if (value != null) {
                    if(value.contains("E") || new BigDecimal(value).scale() < Integer.parseInt(precision)){
                        res.add(item);
                    }
                }
            }

            if(!CollectionUtils.isEmpty(res)){
                log.error("汇率值处理异常,仍存在科学计数法表示或仍存在精度不足尚未补零的汇率。一共有{}条,具体是:{}", res.size(), res);
            }else{
                log.info("汇率值处理成功,所有科学计数法转化完成,所有精度不足的汇率补零完成。");
            }
            return res.size();
        }

        /**
         * 处理列表中的汇率值。
         * @param list 要处理的列表
         * @param precisionPropertyName 精度属性名称
         * @param valuePropertyName 值属性名称
         * @throws NoSuchMethodException 如果指定的方法不存在时抛出此异常
         * @throws InvocationTargetException 在执行目标方法失败时抛出此异常
         * @throws IllegalAccessException 在访问方法时发生非法访问时抛出此异常
         */
        public void processExchangeRateValue(List<T> list, String precisionPropertyName, String valuePropertyName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            if (list == null || list.isEmpty()) {
                throw new IllegalArgumentException("列表不能为null或空");
            }

            for (T item : list) {
                String precision = (String) getProperty(item, precisionPropertyName);
                String value = (String) getProperty(item, valuePropertyName);
                if (value != null) {
                    value = convertScientificNotation(value);
                    value = zeroPadding(value, precision);
                    setProperty(item, valuePropertyName, value);
                }
            }
        }

        /**
         * 根据属性名称获取对象的属性值。
         * @param obj 要获取属性值的对象
         * @param propertyName 属性名称
         * @return 对象的属性值
         * @throws NoSuchMethodException 如果指定的方法不存在时抛出此异常
         * @throws InvocationTargetException 在执行目标方法失败时抛出此异常
         * @throws IllegalAccessException 在访问方法时发生非法访问时抛出此异常
         */
        private Object getProperty(Object obj, String propertyName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            Method method = obj.getClass().getMethod(getGetterName(propertyName));
            return method.invoke(obj);
        }

        /**
         * 根据属性名称设置对象的属性值。
         * @param obj 要设置属性值的对象
         * @param propertyName 属性名称
         * @param value 要设置的属性值
         * @throws NoSuchMethodException 如果指定的方法不存在时抛出此异常
         * @throws InvocationTargetException 在执行目标方法失败时抛出此异常
         * @throws IllegalAccessException 在访问方法时发生非法访问时抛出此异常
         */
        private void setProperty(Object obj, String propertyName, Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            Method method = obj.getClass().getMethod(getSetterName(propertyName), value.getClass());
            method.invoke(obj, value);
        }

        /**
         * 获取指定属性的getter方法名称。
         * @param propertyName 属性名称
         * @return 属性的getter方法名称
         */
        private String getGetterName(String propertyName) {
            return "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
        }

        /**
         * 获取指定属性的setter方法名称。
         * @param propertyName 属性名称
         * @return 属性的setter方法名称
         */
        private String getSetterName(String propertyName) {
            return "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
        }
    }

    /**
     * 根据精度,对汇率值进行补0。
     * @param value 汇率值
     * @param precision 精度
     * @return 补零后的汇率值
     */
    public static String zeroPadding(String value, String precision){
        BigDecimal bigDecimalValue = new BigDecimal(value);
        int intValue = Integer.parseInt(precision);
        BigDecimal bd = bigDecimalValue.setScale(intValue, RoundingMode.HALF_UP);
        return bd.toString();
    }

    /**
     * 将科学计数法表示的数据转化成正常显示的数据。
     * @param input 输入
     * @return 正常显示的数据
     */
    public static String convertScientificNotation(String input) {
        BigDecimal number = new BigDecimal(input);
        return number.toPlainString();
    }

}

你可能感兴趣的:(java,开发语言)