说起java的序列化,我们最初的理解就是形成一个文件,保存到本地,这是最为常用的一点,也算是较为基础的一部分了。
而反射呢,不外乎就是跳过预编译,生成一个对象,代替一个new 的过程。
常用基础的应该就是Class.forName(),和Class.newInstance()这两个方法了。
在这周的空闲时间重新回顾了下java反射的基础,对其有了一个新的理解,其主要的工具包主要是依赖于 java.lang.reflect包中。
用一个情景来进行解释好了,我们设拥有这样的一个场景,
现在我们由一个Data的类(它拥有的属性是任意类型的),然后我们得到了一串关于Data类属性的值,我们通过反射来创建一个拥有实际值的Data对象。
先来总结一下,本次情景主要用到的方法,并且做一个总结:
获取构造方法:
getConstructors():所有"公有的"构造方法
getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
其中要注意的是使用getDeclaredConstructors()获得私有时,需要用到setAccessible()来进行解除限定。
获取类中每一条属性的记录:
getFields():获取所有的"公有字段"
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,Class>type){
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(Class>type){
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),但是需求是一直都在变化的,而这种可拓展性相对来说要高的多。