反射及案例应用

本文深入探讨了Java反射的概念,讲解如何获取类的字节码对象,以及Class类中的关键方法,包括获取成员变量和成员方法。文章通过实例展示了如何使用反射给类的成员变量赋值和调用方法,并讨论了反射在改造项目多方法请求中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射

概述: 在运行期对任意类中任意资源进行任意操作 例如:在程序运行中我们通过获取任意的类的字节码文件、通过对字节码文件进行解刨、对字节码文件中的属性、方法、构造、进行操作(我们可以通过字节码文件给类中的成员变量赋值、获取成员变量的值以及调用类中方法、调用类中构造…)

获取类的字节码对象

@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("查询所有学生");
	}	

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值