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")才可以
写的真糟