Java反射

反射的概念之类的就不写,今天写一下反射的用法以及实例:

package com.zs.entity;

import java.util.Date;

public class Emp {
    public int empno;
    public String ename;
    private String job;
    private int mgr;
    private Date hireDate;
    private double sal;
    private double comm;
    private int deptno;

    public Emp() {
    }

    private Emp(int empno, String ename, double sal) {
        this.empno = empno;
        this.ename = ename;
        this.sal = sal;
    }

    public int getEmpno() {
        return empno;
    }

    public void setEmpno(int empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public int getMgr() {
        return mgr;
    }

    public void setMgr(int mgr) {
        this.mgr = mgr;
    }

    public Date getHireDate() {
        return hireDate;
    }

    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public double getComm() {
        return comm;
    }

    public void setComm(double comm) {
        this.comm = comm;
    }

    public int getDeptno() {
        return deptno;
    }

    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hireDate=" + hireDate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                '}';
    }
}

上面创建实体类,我们通过这个实体类来理解反射

package com.zs.TestDemo;

import com.zs.entity.Emp;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 创建反射对象的三种方式
 * 1.类对象.getClass()
 * 2.类名.class
 * 3.Class.forName();
 * 三种方式常用的是第三种
 */
public class TestDemo {
    public static void main(String[] args) throws Exception {
      /*  1.getClass(),通过下面的代码可以看出,要想使用getClass()方法获得反射对象,
        我们需要先创建一个类的实例化对象,可是我们获得反射就是为了获取实例化对象,已经有了实例化对象,
        就不需要使用反射了,因此这种方法不常用*/
        Emp emp = new Emp();
        Class<? extends Emp> aClass = emp.getClass();

        /*2.类名.class ,这种方式返回的反射对象类型,固定是Emp类型的*/
        Class<Emp> clazz = Emp.class;

        /*3.Class.forName(),这种方式已经比较熟悉了, 在jdbc阶段,加载驱动就是用的这种方法*/
        Class<?> aClass1 = Class.forName("com.zs.entity.Emp");

        /**
         * 下面查看反射对象所具有的方法
         */
        /*1.getDeclaredFields(),获取该类所有的字段属性,包括私有的,
        * getDeclaredField("*"),获取名字为*的属性*/
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        Field ename = clazz.getDeclaredField("ename");
        System.out.println(ename);//public java.lang.String com.zs.entity.Emp.ename

        /*2.上面是加 Declare 的方法,加了Declare就可以获取私有的属性了。不加只能获得修饰符为public的字段属性*/
        Field[] fields1 = clazz.getFields();
        for (Field field : fields1) {
            System.out.println(field);
        }
        Field empno = clazz.getField("empno");



        /*3.与字段相对应, 方法也有这两种方式,添加Declare可以获取包括私有的方法,不加只能获取修饰符为public的方法*/
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        /*获取方法名为**的方法*/
        Method getEmpno = clazz.getDeclaredMethod("getEmpno");

        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        Method getEmpno1 = clazz.getMethod("getEmpno");


        /*4.使用反射对象,创建实例化对象*/
        Emp emp1 = clazz.newInstance();
        /*使用空参的构造方法*/
        Constructor<Emp> constructor = clazz.getConstructor();
        System.out.println(constructor + "11111111111");
        /*有参构造方法,因为有参构造为私有的方法,因此要用有Declare的方法*/
        Constructor<Emp> constructor1 = clazz.getDeclaredConstructor(int.class, String.class, double.class);
        System.out.println(constructor1);
        /*与字段一样,构造方法也有Declare的区分,加了Declare后就可以获取私有的构造方法*/
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        /*5.在这些反射对象的属性中,还有其他的方法*/
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            /*字段的名字以及类型,这两个方法同样可以用在方法上,就不演示了*/
            System.out.println(declaredField.getName() + "11" + declaredField.getType());
        }
        /*具体的方法还有很多,有兴趣可以自己去测试*/
    }
}

反射的具体使用,在之前的jdbc工具类中,我们只能将数据封装入list<map>集合中,因为工具类搜索的表是可变的,因为我们没有办法将对象传递过去,在工具类中,创建不同的对象,所以没有办法在工具类中返回对象的集合,在学习了反射后,就可以将搜索结果存入对象了。

 //查询方法
    public <T> List<T> queryToBean(String sql, Class<?> clazz, Object... args) {

        //创建返回list集合
        List<T> list=new ArrayList<>();
        try {
            //获取结果集
            rs=pretreatmentSql(sql, args).executeQuery();

            //获取反射类的成员变量
            Field[] fs = clazz.getDeclaredFields();

            //遍历结果集每一行
            while (rs.next()) {
                //创建反射类对象
                T t = (T)clazz.newInstance();
                //遍历成员变量
                for (Field f : fs) {
                    //根据成员变量名获取反射类对象的 成员变量对象
                    Field field = t.getClass().getDeclaredField(f.getName());
                    //设置跨越访问权限进行操作
                    field.setAccessible(true);
                    Object object = rs.getObject(f.getName());
                    //给成员变量对象赋值
                    field.set(t, object);
                }
                list.add(t);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

通过以上的方法,在调用方法时,传递要封装对象的class对象,就可以将搜索结果封装为对象了,需要注意的是,这种方法存在一定缺陷就是当数据库连表查询时,需要将你想要的数据字段都在要封装的对象中创建字段,因为是通过字段名到数据库的结果集中获取值的,因此就会造成一个实体类的字段与另一个实体类字段重复等问题。

posted @ 2019-07-18 09:34  Zs夏至  阅读(165)  评论(0编辑  收藏  举报