Java Map 泛型问题 怎么搞才对?

img

listToMap方法返回的Map是string,apple,但是引用的age中的泛型写long, apple或integer,apple都不报错,写long,string也正常报错,求解?



import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class T {

    static class Apple {
        public Apple(String name, String age) {
            this.name = name;
            this.age = age;
        }

        String name;
        String age;

        @Override
        public String toString() {
            return "Apple{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAge() {
            return age;
        }

        public void setAge(String age) {
            this.age = age;
        }
    }

    public static void main(String[] args) {
        ArrayList<Apple> objects = new ArrayList<>();
        objects.add(new Apple("zhang", "5"));

        Map<Long, Apple> age = listToMap(objects, "age");
        Map<Integer, Apple> age1 = listToMap(objects, "age");
        Map<String, Apple> age2 = listToMap(objects, "age");
        System.out.println(age);
        System.out.println(age.get(5L));
    }


    public static <K, V> Map<K, V> listToMap(List<V> list, String fieldName) {
        Map<K, V> map = new HashMap<K, V>();

        for (V v : list) {
            if (v == null) {
                continue;
            }
            if (v instanceof Map) {
                Map temp = (Map) v;
                if (temp.containsKey(fieldName)) {
                    K k = (K) temp.get(fieldName);
                    if (k == null) {
                        continue;
                    }
                    map.put(k, v);
                }
            } else {
                Field field = getFieldByName(v.getClass(), fieldName);
                if (field != null) {
                    K k = invokeGetter(v, fieldName);
                    if (k == null) {
                        continue;
                    }
                    map.put(k, v);
                }
            }
        }
        return map;
    }

    /**
     * 根据属性名获得指定类的属性对象
     *
     * @param clazz
     * @param fieldName
     * @return
     */
    public static Field getFieldByName(Class<?> clazz, String fieldName) {


        Field field = null;

        try {
            field = clazz.getDeclaredField(fieldName);
        } catch (Exception e) {

        }

        return field;
    }

    /**
     * 指定getter方法
     *
     * @param obj
     * @param fieldName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T invokeGetter(Object obj, String fieldName) {
        Method method = getGetterByFieldName(obj.getClass(), fieldName);
        if (method == null) {
            return null;
        }
        try {
            return (T) method.invoke(obj);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 执行指定字段名称对应getter方法
     *
     * @param clazz
     * @param fieldName
     * @return
     */
    public static Method getGetterByFieldName(Class<?> clazz, String fieldName) {

        Method method = null;
        try {
            // getXxx类型
            String methodLowerName = "get" + fieldName.toLowerCase();
            Method[] mehtods = getMehtods(clazz);
            for (Method methodTmp : mehtods) {
                if (methodLowerName.equals(methodTmp.getName().toLowerCase())) {
                    return methodTmp;
                }
            }
            if (method == null) {
                // isXxx类型
                methodLowerName = "is" + fieldName.toLowerCase();
                for (Method methodTmp : mehtods) {
                    if (methodLowerName.equals(methodTmp.getName())) {
                        return methodTmp;
                    }
                }
            }

            return method;
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 获得指定类的所有方法
     *
     * @param clazz
     * @return
     */
    public static Method[] getMehtods(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        try {
            return clazz.getDeclaredMethods();
        } catch (Exception e) {
            return null;
        }
    }
}

invokeGetter方法里,把age强转成你接收返回值的map的第一个泛型了
所以不管你是Map<String, Apple> Map<Interge, Apple> Map<Long, Apple>都不会报错

Map<K, V> 你只指定了 V 的类型是传入的List的泛型 Apple,并没有指定K 是什么类型;你用什么类型作为key都可以;
但是实际转换后的map是已Apple 的age作为key的,所以转换后的map实际是Map<Map, Apple>的, key 5 和 "5" 进过hash后是不一样的,所以用map.get(5) 取不到值,map.get("5")才可以

写的真糟