概述

java范式机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须要先获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法。所以要先获取到每一个字节码文件对应的Class类型的对象

类的加载过程

image.png

Class类

image.png

获取Class类的三种方式

▪ 当用户想要获取任何一个Class类有三种方式:
– Object→getClass()
– 任何数据类型都有一个静态的class属性
– 通过Class.forName()
▪ 三种方式的对比:
– 第一种已经创建对象,就意味着已经产生了Class类
– 第二种需要导入对应的包,依赖太强
– 第三种常用,只需要传入一个类的完全限定名即可

反射的常用api

▪ 获取类的构造方法
▪ 获取类的成员变量
▪ 获取类的成员方法

示例

常用api

package com.msbline.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ClassAPI {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.msbline.reflect.Student");
        //获取成员变量,只能获取到public修饰的成员变量和方法
 Field[] fields = clazz.getFields();
        for(Field field:fields){
            System.out.println(field);
            System.out.println(field.getName());
            System.out.println(field.getType());
            System.out.println(field.getModifiers());
            System.out.println("-----------");
        }
        System.out.println("==================");
        //此方法返回的是当前类的所有属性,不仅仅局限于公共访问修饰符,
 //所有的访问修饰符都可以拿到,但是父类的拿不到
 Field[] declaredFields = clazz.getDeclaredFields();
        for(Field field:declaredFields){
            System.out.println(field);
            System.out.println(field.getName());
            System.out.println(field.getType());
            System.out.println(field.getModifiers());
            System.out.println("-----------");
        }
        System.out.println("========================");
        //反射在一定程度上破坏了封装性,需要合理使用
 Field address = clazz.getDeclaredField("address");
// 设置该属性是否能被访问,true表示可以访问
 address.setAccessible(true);
        System.out.println(address.getName());
        Object o = clazz.newInstance();
        address.set(o,"北京市");
        System.out.println(((Student)o).getAddress());
        System.out.println("========================");
        //获取该对象的普通方法,包含的方法范围是当前对象及父类对象的所有public修饰的方法
 Method[] methods = clazz.getMethods();
        for(Method method:methods){
//            System.out.println(method);
 System.out.println(method.getName());
//            System.out.println(method.getModifiers());
 System.out.println("---------------------");
        }
        System.out.println("====================");
        //获取当前类的所有方法,无论什么访问修饰符,不包括父类
 Method[] declaredMethods = clazz.getDeclaredMethods();
        for(Method method:declaredMethods){
            System.out.println(method.getName());
            System.out.println("---------------------");
        }
        System.out.println("==================");
        Method add = clazz.getDeclaredMethod("add", int.class, int.class);
        add.setAccessible(true);
        Object o1 = clazz.newInstance();
        add.invoke(o1,123,123);
        System.out.println("=====================");
        //获取对象的所有的构造方法,只能获取public修饰的公共的改造方法
 Constructor<?>[] constructors = clazz.getConstructors();
        for(Constructor constructor:constructors){
            System.out.println(constructor.getName());
            System.out.println(constructor.getModifiers());
        }
        System.out.println("=====================");
        //获取所有的构造方法,无论是私有还是共有
 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for(Constructor constructor:declaredConstructors){
            System.out.println(constructor.getName());
            System.out.println(constructor.getModifiers());
        }
        //如何调用私有的构造方法呢?
 Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class, String.class);
        declaredConstructor.setAccessible(true);
        Object o2 = declaredConstructor.newInstance("msb", 44, "java");
        System.out.println(((Student)o));
    }
}

应用

1、实体Emp
package com.msbline.entity;
public class Emp {
    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private String hiredate;
    private Double sal;
    private Double comm;
    private Integer deptno;
    public Emp() {
    }
    public Emp(Integer empno, String ename, String job, Integer mgr, String hiredate, Double sal, Double comm, Integer deptno) {
        this.empno = empno;
        this.ename = ename;
        this.job = job;
        this.mgr = mgr;
        this.hiredate = hiredate;
        this.sal = sal;
        this.comm = comm;
        this.deptno = deptno;
    }
    public Integer getEmpno() {
        return empno;
    }
    public void setEmpno(Integer 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 Integer getMgr() {
        return mgr;
    }
    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }
    public String getHiredate() {
        return hiredate;
    }
    public void setHiredate(String 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 Integer getDeptno() {
        return deptno;
    }
    public void setDeptno(Integer 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 +
                '}';
    }
}
2、实体Dept
package com.msbline.entity;
public class Dept {
    private int deptno;
    private String dname;
    private String loc;
    public Dept() {
    }
    public Dept(int deptno, String dname, String loc) {
        this.deptno = deptno;
        this.dname = dname;
        this.loc = loc;
    }
    public int getDeptno() {
        return deptno;
    }
    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }
    public String getLoc() {
        return loc;
    }
    public void setLoc(String loc) {
        this.loc = loc;
    }
    @Override
 public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + ''' +
                ", loc='" + loc + ''' +
                '}';
    }
}
3、BaseDaoImpl
package com.msbline.reflect;
import com.msbline.entity.Dept;
import com.msbline.jdbc.DBUtil;
import com.msbline.entity.Emp;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
 * 要查询N张表的数据,但是不想写N多方法,
 * 能否写一个方法完成所有表的查询工作
 *
 */public class BaseDaoImpl {
    /**
 * 统一查询表的方法
 * @param sql sql语句
 * @param params sql参数
 * @param clazz sql语句查询返回的对象
 * @return
 */
 public List getRows(String sql,Object[] params,Class clazz){
        List list = new ArrayList();
        Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet resultSet = null;
        try{
            connection = DBUtil.getConnection();
            pstmt = connection.prepareStatement(sql);
            //给sql语句填充参数
 if(params != null){
                for(int i = 0; i<params.length; i++){
                    pstmt.setObject(i+1,params[i]);
                }
            }
            //开始执行查询
 resultSet = pstmt.executeQuery();
            //将返回的结果放置到不同的对象中
 //获取结果集合的元数据对象
 ResultSetMetaData metaData = resultSet.getMetaData();
            //判断查询到的每一行记录中包含多少个列
 int columnCount = metaData.getColumnCount();
            while (resultSet.next()){
                //创建放置具体结果属性的对象
 Object obj = clazz.newInstance();
                for(int i = 0; i<columnCount; i++){
                    //从结果集合中获取单一列的值
 Object objValue = resultSet.getObject(i + 1);
                    //获取列的名称
 String columnName = metaData.getColumnName(i+1).toLowerCase();
                    //获取类中属性的名称
 Field field = clazz.getDeclaredField(columnName);
                    //获取类中属性对应的set方法
 Method method = clazz.getMethod(getSetName(columnName), field.getType());
                    if(objValue instanceof Number){
                        Number number = (Number)objValue;
                        String fname = field.getType().getName();
                        if("int".equals(fname) || "java.lang.Integer".equals(fname)){
                            method.invoke(obj,number.intValue());
                        } else if("byte".equals(fname) || "java.lang.Byte".equals(fname)){
                            method.invoke(obj,number.byteValue());
                        }else if("short".equals(fname) || "java.lang.Short".equals(fname)){
                            method.invoke(obj,number.shortValue());
                        }else if("long".equals(fname) || "java.lang.Long".equals(fname)){
                            method.invoke(obj,number.longValue());
                        }else if("float".equals(fname) || "java.lang.Float".equals(fname)){
                            method.invoke(obj,number.floatValue());
                        }else if("double".equals(fname) || "java.lang.Double".equals(fname)){
                            method.invoke(obj,number.doubleValue());
                        }
                    } else {
                        method.invoke(obj,objValue);
                    }
                }
                list.add(obj);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,pstmt,resultSet);
        }
        return list;
    }
    public String getSetName(String name){
        return "set"+name.substring(0,1).toUpperCase()+name.substring(1);
    }
    public static void main(String[] args) {
        BaseDaoImpl baseDao = new BaseDaoImpl();
//        List rows = baseDao.getRows("select empno,ename,sal,deptno from emp where deptno=?",
//                new Object[]{10}, Emp.class);
 List rows = baseDao.getRows("select deptno,dname,loc from dept",
                new Object[]{}, Dept.class);
        System.out.println(rows.size());
        for(Iterator iterator = rows.iterator();iterator.hasNext();){
            Dept dept = (Dept) iterator.next();
            System.out.println(dept);
        }
    }
}

萌妹子_liu
28 声望43 粉丝

萌萌哒,程序猿