反射
概述: 在运行期对任意类中任意资源进行任意操作 例如:在程序运行中我们通过获取任意的类的字节码文件、通过对字节码文件进行解刨、对字节码文件中的属性、方法、构造、进行操作(我们可以通过字节码文件给类中的成员变量赋值、获取成员变量的值以及调用类中方法、调用类中构造…)
获取类的字节码对象
@Test
public void getClass_01() throws Exception {
// 方式一
Class<?> claz = Class.forName("com.offcn.entity.Student");
System.out.println(claz);
// 方式二
Class<?> claz1 = Student.class;
System.out.println(claz1);
// 方式三
Student student = new Student();
Class<? extends Student> claz2 = student.getClass();
System.out.println(claz2);
}
Class类中的方法
获取类中的成员变量
API
公有属性getField(属性名)
私有属性getDeclaredField(属性名)
@Test
public void getFiled() throws Exception {
// public类型的属性操作
Class<?> claz = Class.forName("com.offcn.entity.Student");
// 获取public类型age属性
Field age = claz.getField("age");
// Student stu = new Student();// == Student stu = (Student) claz.newInstance();
Student stu = (Student) claz.newInstance(); // 创建对象
// 给属性赋值
age.set(stu, 10);
System.out.println(stu);
// 获取private类型name属性
Field name = claz.getDeclaredField("name");
// 开启暴力访问 true开启 false 关闭默认
name.setAccessible(true);
// 给name赋值
name.set(stu, "孙悟空");
System.out.println(stu);
}
获取类中的成员方法
API
公有方法getMethod(方法名,参数类型…)
私有方法getDeclaredMethod(方法名,参数类型…)
@Test
public void getMehod() throws Exception {
// 获取字节码文件
Class<?> claz = Class.forName("com.offcn.entity.Student");
//获取public类型的方法
Method m =claz.getMethod("show");
//创建对象
Student stu = (Student) claz.newInstance();
//方法执行
m.invoke(stu);
//获取public类型的方法 带参数
Method m1 = claz.getMethod("show", int.class,String.class);
//方法执行
m1.invoke(stu, 18,"藏獒十三");
//获取public类型的方法 带返回值和方法
Method m2 = claz.getMethod("getSum", int.class,int.class);
//方法执行
Object sum = m2.invoke(stu, 10,20);
System.out.println(sum);
//获取私有方法
Method show1 = claz.getDeclaredMethod("show1");
//开启暴力访问
show1.setAccessible(true);
//方法执行
show1.invoke(stu);
//获取私有方法 带参数的
Method m4 = claz.getDeclaredMethod("show1", int.class);
//开启暴力访问
m4.setAccessible(true);
//方法执行
m4.invoke(stu,20);
}
案例应用
概述:创建一个user类 类中4个属性 2个私有2个公有 通过反射的方法封装内容
public class Demo_fs {
/*
* 不使用set方法给属性赋值 并打印对象 private uid name public age sex
*/
@Test
public void createUser() throws Exception {
//获取user类的字节码文件
Class<?> claz = Class.forName("com.offcn.entity.User");
//创建user对象
User u = (User) claz.newInstance();
//获取属性
Field uid = claz.getDeclaredField("uid");
//开启暴力访问
uid.setAccessible(true);
//赋值
uid.set(u, 1);
Field name = claz.getDeclaredField("name");
//开启暴力访问
name.setAccessible(true);
//赋值
name.set(u, "藏獒十三");
Field age = claz.getField("age");
//赋值
age.set(u, 10);
Field sex = claz.getField("sex");
//赋值
sex.set(u, "男");
System.out.println(u);
}
/*
* 只能使用set方法完成赋值
*/
@Test
public void createUser1() throws Exception {
//获取字节码文件
Class<?> claz = Class.forName("com.offcn.entity.User");
//创建对象
User u = (User) claz.newInstance();
//获取方法
Method setUid = claz.getMethod("setUid", int.class);
//方法执行
setUid.invoke(u, 1);
Method setName = claz.getMethod("setName", String.class);
//方法执行
setName.invoke(u, "泰日天");
Method setAge = claz.getMethod("setAge", int.class);
//方法执行
setAge.invoke(u, 3);
Method setSex = claz.getMethod("setSex", String.class);
//方法执行
setSex.invoke(u, "公");
System.out.println(u);
}
}
使用反射改造项目多方法请求
baseServlet
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要访问的具体方法
String method = req.getParameter("method");
System.out.println(method);
//获取子类的字节码文件
Class<? extends BaseServlet> claz =this.getClass();
//根据方法名和方法的参数类型去字节码中获取到该方法
try {
Method m = claz.getMethod(method, HttpServletRequest.class,HttpServletResponse.class);
//方法执行
m.invoke(claz.newInstance(), req,resp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
页面-index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="/day14/student?method=findAll">查询学生</a><br>
<a href="/day14/student?method=update">修改学生</a><br>
<a href="/day14/student?method=add">添加学生</a><br>
<a href="/day14/student?method=delete">删除学生</a><br>
</body>
</html>
StudentServlet
@WebServlet("/student")
public class StudentServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要访问的业务方法
String method = req.getParameter("method");
if(method.equals("findAll")) {
findAll(req,resp);
}else if(method.equals("add")) {
add(req,resp);
}else if(method.equals("update")) {
update(req,resp);
}else if(method.equals("delete")) {
delete(req,resp);
}
}
//处理删除
private void delete(HttpServletRequest req, HttpServletResponse resp) {
// TODO Auto-generated method stub
System.out.println("删除学生");
}
//处理修改
private void update(HttpServletRequest req, HttpServletResponse resp) {
// TODO Auto-generated method stub
System.out.println("修改学生");
}
/*
* 处理添加
*/
private void add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("添加学生");
}
/*
* 处理查询所有
*/
private void findAll(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("查询所有学生");
}
}