Java 反射---数据序列化成对象 总结

说起java的序列化,我们最初的理解就是形成一个文件,保存到本地,这是最为常用的一点,也算是较为基础的一部分了。

而反射呢,不外乎就是跳过预编译,生成一个对象,代替一个new 的过程。

常用基础的应该就是Class.forName(),和Class.newInstance()这两个方法了。

在这周的空闲时间重新回顾了下java反射的基础,对其有了一个新的理解,其主要的工具包主要是依赖于 java.lang.reflect包中。

用一个情景来进行解释好了,我们设拥有这样的一个场景,

现在我们由一个Data的类(它拥有的属性是任意类型的),然后我们得到了一串关于Data类属性的值,我们通过反射来创建一个拥有实际值的Data对象。

先来总结一下,本次情景主要用到的方法,并且做一个总结:

获取构造方法:

getConstructors():所有"公有的"构造方法
getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

其中要注意的是使用getDeclaredConstructors()获得私有时,需要用到setAccessible()来进行解除限定。

获取类中每一条属性的记录:

  1. getFields():获取所有的"公有字段"

  2. getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有

其中要注意的一项是反射生成的是一个对象的数据,而不是一个类。因此对于获取到的静态变量,其实属于整个类的,不加入反射。

获取方法,调用方法:

1.批量的:

public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)

public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)

2.获取单个的:

public Method getMethod(String name,Class... parameterTypes):

*参数:

* name : 方法名;

* Class ... : 形参的Class类型对象

* public Method getDeclaredMethod(String name,Class... parameterTypes)

* 调用方法:

* Method --> public Object invoke(Object obj,Object... args):

* 参数说明:

* obj : 要调用方法的对象;

* args:调用方式时所传递的实参;

为了区分概念免得混淆代码先来一个简陋的识别:

Field:代表整一条的属性。

Class:修饰词(例如String类,Interge类这些)

Object:值(储存的是值,例如String name = “11211”,其中Object指的是11211)

下面是代码实现部分:

主测试类:

public class ReflectData {
	
	private static  final ReflectModel reflectModel = new ReflectModel<>(Data.class);
	
	
	public static void main(String[] args){
		Data data = getData();
		System.out.println(data.toString());
		
	}
	
	//通过反射得到一个Data对象
	private static Data getData(){
		return  reflectModel.getData();
	}
	
	private static class Data{
		String name;
		int age;
		Boolean sex;
		
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return "name : "+name+",age:" +age+"sex: "+sex;
		}
		
	}
}

其中Data类为本次的场景的测试对象

反射处理model类:


import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;

public class ReflectModel {
    
	
	private final compositionModel extractor;//储存了modelclass、 构造方法、Map
	private final serialMap  serialmap; //对给定的对象的实际值,进行转化赋值的类,
	private final Map> typeMap;
	
	ReflectModel(Class modelClass){
		this.extractor = new compositionModel(modelClass);
		this.serialmap = new serialMap();
		this.typeMap = getTypeMap();
	}
	
	private Map> getTypeMap(){
		Map sf = this.extractor.getFieldContain();
		Map> sc = new LinkedHashMap>();
		for(String s:sf.keySet()){
			sc.put(s, sf.get(s).getType());
		}
		return sc;
	}
	
	public Model getData(){
		String dataString ="sss,18,1";
		Model model = deserialize(dataString);
		return model;
	}
	
	public Model deserialize(String dt){
		Model model = extractor.newInstance();
		Map values = extractor.getValues(model);
		serialmap.deserialize(dt, values, typeMap);
		extractor.setValue(model, values);
		return model;
	}
}

model的反射解析类:


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.Map;

public class compositionModel {
	 
	private final Class modelClass;
	private final Constructor modelConstructor;
	private final Map  fieldContain;
	
	compositionModel(Class cl){
		this.modelClass = cl;
		this.modelConstructor = getModelConstrutor(cl);
		this.fieldContain = getFieldContain(cl);
	}
	
	public Map getFieldContain(){
		return fieldContain;
	}
	
	//设置值
	public void setValue(Model model,Map values){
		for(String s:values.keySet()){
			Field f = fieldContain.get(s);
			try {
				f.set(model,values.get(s));//filed.set()方法对model中该f属性赋值
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	//获得构造方法
	private Constructor getModelConstrutor(Class cl){
		try {
			Constructor modelConstructor = cl.getDeclaredConstructor(new Class[] {});
			modelConstructor.setAccessible(true);
			return modelConstructor;
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		///return modelConstructor;
		return null;
		
	}
	
	//通过构造器获取model实例
	Model newInstance(){
		try {
			return modelConstructor.newInstance();
		} catch (InvocationTargetException e) {
			//构造函数本身抛出异常,将尽量把异常以 unchecked 形式抛出。
			Throwable targetException = e.getTargetException();
			if(targetException instanceof Error) {
				throw (Error) targetException;
			} else if(targetException instanceof RuntimeException) {
				throw (RuntimeException) targetException;
			} else {
				throw new RuntimeException(targetException);
			}
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
		
	}
	
	//获取对象属性,排除static和fianl的属性
	private  Map getFieldContain(Class cl){
		Map fc = new LinkedHashMap();
		for(Field f:cl.getDeclaredFields()){
			int modifiers = f.getModifiers();
			//与序列化一致,静态变量是属于全局的,不是属于对象的,不加入反射
			if(!Modifier.isFinal(modifiers) && !Modifier.isStatic(modifiers)){
				f.setAccessible(true);
				fc.put(f.getName(), f);
			}
		}
		return fc;
	}
	
	//获取每个类的默认值,此处还有拓展,如果实际值没有的话,可以用设置一个map储存每一种类型的默认值
	@SuppressWarnings("unchecked")
	public Map getValues(Model model){
		Map so = new LinkedHashMap(fieldContain.size());
		for(String s:fieldContain.keySet()){
			Field field = fieldContain.get(s);
			try {
				so.put(s, field.get(model));//field.get获取该属性在某个class中的值
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		}
		return so;
		
	}
	
}

传入实际值的赋值处理类:


import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class serialMap {
	
		private static final Map, Class> typeMap = new HashMap, Class>() {{
				
				//Java 除了 char 的 7 种基本类型,外加它们的封包类,外加 String,一共15种类型。
				put(byte.class, Byte.class);
				put(short.class, Short.class);
				put(int.class, Integer.class);
				put(long.class, Long.class);
				put(float.class, Float.class);
				put(double.class, Double.class);
				put(boolean.class, Boolean.class);
				put(Byte.class, Byte.class);
				put(Short.class, Short.class);
				put(Integer.class, Integer.class);
				put(Long.class, Long.class);
				put(Float.class, Float.class);
				put(Double.class, Double.class);
				put(Boolean.class, Boolean.class);
				put(String.class, String.class);
			}};
		
			
		//获取所有的对应类的赋值方法	
		private static final Map, Method> valueOfMethodMap = getValueOfMethodMap();
			
		//解析s数据,并且生成具体的对象,put进value中	
		void deserialize(String s,Map values,Map> typeList){
			String[] sList = s.split("\\,");
			int i=0;
			for(String fieldName:typeList.keySet()){
				Class type = typeList.get(fieldName);
				Object value = getValueFromGetter(sList[i++],type);
				values.put(fieldName, value);
			}
		}
		
		//得到Method类(方法),然后下一步可以调用该方法
		private static Map, Method> getValueOfMethodMap() {
			HashMap, Method> map = new HashMap,Method>();
			for(Class key:typeMap.keySet()){
				Class type = typeMap.get(key);
				Method  method = map.get(type);
				if(method == null){
					Class[] typeClasses;
					if(type.equals(String.class)) {
						typeClasses = new Class[] {Object.class};
					} else {
						typeClasses = new Class[] {String.class};
					}
					try {
						method =  type.getMethod("valueOf", typeClasses);//class.getMethod(“a”,b),class表示想要从中调用方法的类,a表示方法名字,b表示参数所属的类
					} catch (NoSuchMethodException | SecurityException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					map.put(type, method);
				}
			}
			return map;
		}
		
		//获得一个对象的值,例如int可以调用Interge的valueof的方法返回一个Interge对象
		Object getValueFromGetter(String s,Classtype){
			
			Object value = null;
			if(isBooleanType(type)){
				value = "1".equals(s);
			}else{
				Method method = getValueOfMethod(type);
				try {
					value = method.invoke(null, s); //调用方法
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return value;
		}
		Method getValueOfMethod(Classtype){
			type = typeMap.get(type);
			return valueOfMethodMap.get(type);
		}
		private static boolean isBooleanType(Class type) {
			return boolean.class.equals(type) || Boolean.class.equals(type);
		}
		
}

测试结果

总结:reflect包类下有着许多有趣的类,上面的例子用的比较多的泛型,对于可变性有着很大的支持性,而反射也是对着适用性会有很大的变通,虽然看起来反射就是相当于new Data(“sss”,18,true),但是需求是一直都在变化的,而这种可拓展性相对来说要高的多。

你可能感兴趣的:(Java,基础)