java之反射

什么是反射?

反射就是根据类的字节码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;
    }
}

 

posted @ 2021-04-07 10:16  小boboa  阅读(62)  评论(0编辑  收藏  举报