什么是反射?
反射就是根据类的字节码class文件获取一个类的细节,包括构建出来,通过对象去调用方法,访问属性。
为什么使用反射?
可以将要创建的对象,要调用的方法写到配置文件,然后通过反射来完成方法调用,从而降低了代码的耦合性。
反射调用方法实现步骤
1.获取类的字节码
class clazz = Student.class;
2.通过字节码去创建对象
//通过字节码调用newlnstance方法创建对象,其实底层是调用的是字节码对应类中默认构造函数
Student student = clazz.newlnstance(); //获取类的字节码时已经指定了类型,在这就不需要强制转换了
3.反射得到要调用的方法对象method
Method [] methods = clazz.getMethods(); //获取当前类的所有public方法
Method method = clazz.getMethod("setName",String.class);
4.通过反射调用方法
method.invoke(student,"张三");
Method getnamemethod= clazz.getMethod("getName");
Object value = getnamemethod.invoke(student);
然后就是名字就是value值了
注意:
1.如果一个解析xml文件的代码,并且会把解析出来的数据封装到一个对象中(student类)去,在xml文件标签名改了以后,也要把对象中(student类中的全局变量名也要改)全局变量名也要改,要不然反射时就找不到set或者get方法
2.所以,当xml文件的标签名改了,正常调用解析封装到对象的代码就要改 对象和解析代码这几个地方,但反射的方法就只需要改对象中的全局变量就够了,反射方法代码不需要改
test2.xml文件
<?xml version="1.0" encoding="utf-8"?> <students> <!--这个是xml的注释格式--> <student> <StudentName>赵尼玛</StudentName> <StudentAge>28</StudentAge> <StudentGender>女</StudentGender> </student> </students>
普通方法去解析这个xml文件中的学生信息,并封装到Student对象中去
package com.my.packge6; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.File; import java.util.ArrayList; import java.util.List; public class Parse1 { public static void main(String[] args) { Parse1 parse1 = new Parse1(); List<Student> stulist = parse1.parse("src\main\test2.xml"); for (Student student : stulist) { System.out.println(student); } } public List<Student> parse(String filepath){ //1.准备解析器对象 SAXReader saxReader = new SAXReader(); //2.获取Document对象 try { Document document = saxReader.read(new File(filepath)); //3.获取根节点 Element root = document.getRootElement(); //4.根据根节点遍历子节点,返回的是个列表 List<Element> studentsElement= root.elements("student"); //写个集合 List<Student> list = new ArrayList<Student>(); //5.通过循环取出每一个student元素进行处理 for (Element studentelement : studentsElement) { String name = studentelement.elementText("StudentName"); String age = studentelement.elementText("StudentAge"); String gender = studentelement.elementText("StudentGender"); //拿到值封装到student对象中去 Student student = new Student(name,age,gender); list.add(student); } return list; } catch (Exception e) { e.printStackTrace(); } return null; } }
然后,这是通过反射去实现:
package com.my.packge6; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public class Parse2 { public static void main(String[] args) { Parse2 parse1 = new Parse2(); List<Student> stulist = parse1.parse("src\main\test2.xml"); for (Student student : stulist) { System.out.println(student); } } public List<Student> parse(String filepath){ //1.准备解析器对象 SAXReader saxReader = new SAXReader(); //2.获取Document对象 try { Document document = saxReader.read(new File(filepath)); //3.获取根节点 Element root = document.getRootElement(); //4.根据根节点遍历子节点,返回的是个列表 List<Element> studentsElement= root.elements("student"); //写个集合 List<Student> list = new ArrayList<Student>(); //拿到学生类的字节码 Class<Student> clazz =Student.class; //5.通过循环取出每一个student元素进行处理 for (Element studentelement : studentsElement) { //通过反射创建学生对象 Student student = clazz.newInstance(); //获取xml文件中子标签 List<Element> stuchildelements= studentelement.elements(); for (Element stuchildelement : stuchildelements) { String eleName = stuchildelement.getName(); //获取子标签的值 String value = stuchildelement.getText(); //拼接方法名,得到要调用的方法 String methodname = "set"+eleName; //调用setName方法来封装学生的姓名;getMethod方法中传入的是需要调用的方法名和该方法入参类型,没有入参类型,可以只填方法名 //反射得到要调用的方法对象 Method method = clazz.getMethod(methodname,String.class); //通过方法对象反射调用setName方法 method.invoke(student, value); } list.add(student); } return list; } catch (Exception e) { e.printStackTrace(); } return null; } }