package map;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: lyf
* @Date: 2019-08-09 17:50
* @Description: User user=new User();
* 之前一直区分不出getField()和getDeclareFiled()这两种的具体用法,只知道getDeclareFiled()方法是拿到
* User类型中的所有属性(不包含父类的任何属性),却不知道getField()拿出来的是什么东西,但经过调试之后,我总结
* 出了用法.
* getDeclareFiled()获取的是User类型里面的所有属性
* getField()获取到的是User及其父类的所有public属性
* 相信getMethod()和getDeclareMethod()也是上面的这个意思
* 具体的还需大家一起验证指正
* <p>
* 下面介绍三种检验类型信息的方法
* 1.instanceof关键字
* User user=new User();
* System.out.println(user instanceof User);//user对象是不是就是User类型,或者说user对象是不是就是User扩展类的实现类
* a instanceof B 其中a是对象,B是类名.这个表达式的意思就是:'a对象对应的类型是A,只要A==B或者是A基础与B,那么就返回true'
* 2.使用类型信息class
* BaseClass base=new BaseClass();
* User user=new User();//这里假设User继承了BaseClass
* System.out.println(user.getClass!=base.getClass())//输出true,因为两者的类型信息是不一样的
* System.out.println(user instanceof BaseClass);//输出true,因为user是BaseClass扩展类的实现类
* 这种情况,只有当两者的类型都是同一个的时候才返回true.子类的类型信息!=父类的类型信息
* 3.使用isInstance()方法
* User user=new User();
* Class<User> clazz=user.getClass();//获取User类的类型信息
* System.out.println(clazz.isInstance(user));//动态的判断user对象的类型信息是不是就是clazz
*/
public class MapTest {
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>(1);
map.put("arr", new Integer[]{1, 2, 3, 4, 5, 6, 7});
map.put("intArr", new int[]{1, 2, 3, 4, 5, 6, 7});
map.put("age", 22);
User user = MapUtils.mapToObject(map, User.class);
System.out.println(ReflectionToStringBuilder.toString(user));
}
}
class User extends BaseClass {
private Integer[] arr;
private int age;
public Integer[] getArr() {
return arr;
}
public void setArr(Integer[] arr) {
this.arr = arr;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class BaseClass {
private int[] intArr;
public int[] getIntArr() {
return intArr;
}
public void setIntArr(int[] intArr) {
this.intArr = intArr;
}
}
package map;
import java.lang.reflect.Field;
import java.util.Map;
/**
* @Auther: lyf
* @Date: 2019-08-09 17:38
* @Description:
*/
public abstract class MapUtils {
/**
* 将Map装换成类型T的对象
* 前端传JSON格式的时候,可以先使用Map来接收参数,然后再使用这个方法来进行参数值的获取,以提高接收JSON格式时的接口扩展性
* 意思是:controller的方法里一般都是使用类来接收参数,当使用@RequestBody注解后,该接口只能接收类里面所包含的属性
* 如果存在其他属性的话就会找不到这个接口(就会出现404,使用了@RequestParam注解估计效果也会是404,大家可以试一下),
* 所以为了提高接口的扩展性的话,就得先用Map接收参数,
* 然后再从Map中获取参数值赋值给表单
*
* @param model
* @param clazz
* @param <T>
* @return
*/
public static <T> T mapToObject(Map<String, Object> model, Class<T> clazz) {
T t = null;
try {
t = clazz.newInstance();
//getFields()获取到所有public属性,包含基类和扩展类
//clazz.getDeclaredFields()获取到扩展类的所有属性,包含private属性
Field[] fields = clazz.getDeclaredFields();
if (fields != null && fields.length > 0) {
//遍历所有属性
for (Field field : fields) {
//通过属性的名称去Map中取数据
Object fieldValue = model.get(field.getName());
if (fieldValue != null) {
//如果数据存在的话,就判断数据类型是否一致,一致就将值设置到t对象中
//从而实现赋值操作
if (field.getType() == fieldValue.getClass()) {
//这里除了8大基本数据类型外的其他类型形式都支持
//只要类型一致就能进行操作,想满足其他情况需要自己做兼容操作
field.setAccessible(true);
field.set(t, fieldValue);
}
}
}
}
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return t;
}
}