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