当前位置: 首页 > news >正文

反射之专题

动态代理

特点:无侵入式的给代码增加额外的功能

程序为什么需要代理?代理长什么样子?

对象如果嫌身上干的事太多的话,可以通过代理来转移部分职责。

对象有什么方法想被代理,代理就一定要有对应的方法。代理里面就是对象要被代理的方法

中介如何知道要派有唱歌、跳舞方法的代理呢?

接口

Java通过什么来保证代理的样子?

通过接口保证,后面的对象和代理需要实现同一个接口,接口中就是被代理的所有方法。

如何为Java对象创建一个代理对象?

proxy(代理)

java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
//参数一:用于指定用哪一个类加载器,去加载生成的代理类
//参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
//参数三:用来指定生成的代理对象要干什么事情

在这里插入图片描述

class BigStar implements Star
{private String name;public BigStar(){}public BigStar(String name){this.name = name;}//唱歌@Overridepublic String sing(String name){System.out.println(this.name + "正在唱" + name);return "谢谢";}//跳舞@Overridepublic void dance(){System.out.println(this.name + "正在跳舞");}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
interface Star
{//我们可以把所有想要被代理的方法定义在接口当中//唱歌public abstract String sing(String name);//跳舞public void dance();
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;class ProxyUtil
{/***	方法的作用:给一个明星的对象,创建一个代理*	形参:被代理的明星对象返回值:给明星创建的代理*//***   需求:*   	外面的人想要大明星唱一首歌*   	1、获取代理的对象*   	  代理对象 = ProxyUtil.createProxy(大明星的对象)*   	2、再调用代理的唱歌方法*   	  代理对象,唱歌的方法("只因你太美");*/public static Star createProxy(BigStar bigStar){/**public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)参数一:用于指定用哪一个类加载器,去加载生成的代理类参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法参数三:用来指定生成的代理对象要干什么事情*/Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),  //参数一:用于指定用哪一个类加载器,去加载生成的代理类/ 类加载器  基本固定格式new Class[]{Star.class},   //参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法new InvocationHandler() {  //参数三:用来指定生成的代理对象要干什么事情@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {/*** 参数一:代理的对象* 参数二:要运行的方法 sing* 参数三:调用sing方法时,传递的实参*/if("sing".equals(method.getName())){System.out.println("准备话筒,收钱");}if("dance".equals(method.getName())){System.out.println("准备场地,收钱");}//去找大明星开始唱歌或跳舞//代码的表现形式:调用大明星里面唱歌或跳舞的方法return method.invoke(bigStar,args);}});return star;}
}
public class Test {public static void main(String[] args) {/***   需求:*   	外面的人想要大明星唱一首歌*   	1、获取代理的对象*   	  代理对象 = ProxyUtil.createProxy(大明星的对象)*   	2、再调用代理的唱歌方法*   	  代理对象,唱歌的方法("只因你太美");*///1、获取代理的对象BigStar bigStar = new BigStar("鸡哥");Star proxy = ProxyUtil.createProxy(bigStar);//2、调用唱歌的方法String result = proxy.sing("《只因你太美》");System.out.println(result);//3、调用跳舞的方法proxy.dance();}}
总结

1、Java提供了什么API帮我们创建代理?

2、newProxyInstance方法在创建代理时,需要几个参数,每个参数的含义是什么?

3、通过invokehandler的invoke方法指定代理干的事时,这个invoke会被谁调用?要接那几个参数?

反射

什么是反射?

反射允许对成员变量,成员方法和构造方法的信息进行编程访问。

在这里插入图片描述

获取class对象的三种方式

  • Class.forName(“全类名”);
  • 类名.class
  • 对象.getClass();

三种方式对应三种阶段

在这里插入图片描述

获取class对象
package 反射.src;public class MyReflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {/**获取class对象的三种方式:- Class.forName("全类名");- 类名.class- 对象.getClass();*///1、第一种方式//全类名:包名 + 类名//最为常用Class<?> clazz1 = Class.forName("反射.src.Student");//2、第二种方式//一般更多的是当作参数进行传递Class<?> clazz2 = Student.class;//3、第三种方式//当我们已经有了这个类的对象时,才可以使用Student student = new Student();Class<?> clazz3 = student.getClass();System.out.println(clazz1 == clazz2);System.out.println(clazz2 == clazz3);}}

在这里插入图片描述

反射获取构造方法

在这里插入图片描述

权限修饰符对应的数字:

在这里插入图片描述

package 反射.src.myreflect2;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;public class MyReflectDemo2 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/**Class类中用于获取构造方法的方法Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象Constructor类中用于创建对象的方法T newInstance(Object... initargs): 根据指定的构造方法创建对象setAccessible(boolean flag):设置为true,表示取消访问检查
*///1、获取class字节码文件对象Class<?> clazz = Class.forName("反射.src.myreflect2.Student");//2、获取构造方法Constructor<?>[] constructors = clazz.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}System.out.println("\n");//3、获取所有构造方法Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}System.out.println("\n");//4、获取指定构造方法Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();System.out.println(declaredConstructor);System.out.println("\n");Constructor<?> declaredConstructor1 = clazz.getDeclaredConstructor(String.class);System.out.println(declaredConstructor1);System.out.println("\n");Constructor<?> declaredConstructor2 = clazz.getDeclaredConstructor(int.class);System.out.println(declaredConstructor2);System.out.println("\n");Constructor<?> declaredConstructor3 = clazz.getDeclaredConstructor(String.class, int.class);System.out.println(declaredConstructor3);//参照权限修饰符对应的整数int modifiers = declaredConstructor3.getModifiers();//获取构造方法的修饰符System.out.println("modifiers: " + modifiers);Parameter[] parameters = declaredConstructor3.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//private修饰符会报错所以采用暴力反射//暴力反射:临时取消权限校验declaredConstructor3.setAccessible(true);Student student = (Student) declaredConstructor3.newInstance("张三", 18);System.out.println(student.toString());}}
public 反射.src.myreflect2.Student()
public 反射.src.myreflect2.Student(java.lang.String)public 反射.src.myreflect2.Student()
public 反射.src.myreflect2.Student(java.lang.String)
protected 反射.src.myreflect2.Student(int)
private 反射.src.myreflect2.Student(java.lang.String,int)public 反射.src.myreflect2.Student()public 反射.src.myreflect2.Student(java.lang.String)protected 反射.src.myreflect2.Student(int)private 反射.src.myreflect2.Student(java.lang.String,int)
modifiers: 2
java.lang.String arg0
int arg1
Student{age=18, name='张三'}
package 反射.src.myreflect2;public class Student {private String name;private int age;public Student(){}public Student(String name){this.name = name;}protected Student(int age){this.age = age;}private Student(String name, int age){this.name = name;this.age = age;}public String getName(){return name;}public void setName(String name){this.name = name;}public int getAge(){return age;}public void setAge(int age){this.age = age;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}
}
反射获取成员变量

在这里插入图片描述

package 反射.src.myreflect3;import java.lang.reflect.Field;public class myReflectDemo3 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {/*** Class类中用于获取成员变量的方法* Field[] getFields():返回所有公共成员变量对象的数组* Field[] getDeclaredFields():返回所有成员变量对象的数组* Field getField(String name):返回单个公共成员变量对象* Field getDeclaredField(String name):返回单个成员变量对象** Field类中用于创建对象的方法* void set(Object obj, Object value):赋值* Object get(Object obj)获取值。*///1、获取class字节码文件的对象Class<?> clazz = Class.forName("反射.src.myreflect3.Student");//2、获取所有成员变量Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {System.out.println(field);}System.out.println("\n");for (Field field : fields) {System.out.println(field.getName());}System.out.println("\n");//3、获取单个成员变量Field nameField = clazz.getDeclaredField("name");System.out.println(nameField);System.out.println(nameField.getName());//成员变量获取到了。利用成员变量获取其他System.out.println("\n");//4、获取成员变量的修饰符int modifiers = nameField.getModifiers();System.out.println(modifiers);//5、获取成员变量的数据类型Class<?> type = nameField.getType();System.out.println(type);System.out.println("\n");//获取成员变量记录的值Student student = new Student("张三", 20, "男");nameField.setAccessible(true);Object o = nameField.get(student);System.out.println(o);//修改对象里面记录的值nameField.set(student,"李四");System.out.println(student.toString());}}
private java.lang.String 反射.src.myreflect3.Student.name
private int 反射.src.myreflect3.Student.age
public java.lang.String 反射.src.myreflect3.Student.gendername
age
genderprivate java.lang.String 反射.src.myreflect3.Student.name
name2
class java.lang.String张三
Student{age=20, name='李四', gender='男'}
package 反射.src.myreflect3;public class Student {private String name;private int age;public String gender;public Student(){}public Student(String name,int age,String gender){this.name=name;this.age=age;this.gender=gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +", gender='" + gender + '\'' +'}';}
}
反射获取成员方法

在这里插入图片描述

package 反射.src.myreflect4;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;import static java.lang.Character.getName;public class myReflectDemo4 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {/*** Class类中用于获取成员方法的方法* Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的* Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的* Method getMethod(String name, Class<?>... parameterTypes) :返回单个公共成员方法对象* Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象** Method类中用于创建对象的方法* Object invoke(Object obj, Object... args):运行方法* 参数一:用obj对象调用该方法* 参数二:调用方法的传递的参数(如果没有就不写)* 返回值:方法的返回值(如果没有就不写)*** 获取方法的修饰符* 获取方法的名字* 获取方法的形参* 获取方法的返回值* 获取方法的抛出的异常*/Class<?> clazz = Class.forName("反射.src.myreflect4.Student");Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method);}System.out.println("\n");Method[] declaredMethods = clazz.getDeclaredMethods();for (Method method : declaredMethods) {System.out.println(method);}System.out.println("\n");Method getName = clazz.getMethod("getName", null);System.out.println(getName);System.out.println(getName.getName());Method setName = clazz.getMethod("setName", String.class);System.out.println(setName);Method eat = clazz.getDeclaredMethod("eat", String.class);System.out.println("eat:" + eat);//获取修饰符System.out.println(eat.getModifiers());//获取返回值类型System.out.println(eat.getReturnType());//获取方法名System.out.println(eat.getName());//获取方法的返回值类型System.out.println(eat.getReturnType());//获取方法的形参类型Class<?>[] parameterTypes = eat.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println(parameterType);}//获取方法的异常类型Class<?>[] exceptionTypes = eat.getExceptionTypes();for (Class<?> exceptionType : exceptionTypes) {System.out.println(exceptionType);}//调用方法eat.setAccessible(true);Student student = (Student)clazz.newInstance();eat.invoke(student, "米饭");}}
public java.lang.String 反射.src.myreflect4.Student.getName()
public java.lang.String 反射.src.myreflect4.Student.toString()
public void 反射.src.myreflect4.Student.sleep()
public void 反射.src.myreflect4.Student.setName(java.lang.String)
public int 反射.src.myreflect4.Student.getAge()
public void 反射.src.myreflect4.Student.setAge(int)
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public final void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedExceptionpublic java.lang.String 反射.src.myreflect4.Student.getName()
public java.lang.String 反射.src.myreflect4.Student.toString()
public void 反射.src.myreflect4.Student.sleep()
public void 反射.src.myreflect4.Student.setName(java.lang.String)
public int 反射.src.myreflect4.Student.getAge()
public void 反射.src.myreflect4.Student.setAge(int)
private void 反射.src.myreflect4.Student.eat(java.lang.String)public java.lang.String 反射.src.myreflect4.Student.getName()
getName
public void 反射.src.myreflect4.Student.setName(java.lang.String)
eat:private void 反射.src.myreflect4.Student.eat(java.lang.String)
2
void
eat
void
class java.lang.String
吃米饭
package 反射.src.myreflect4;public class Student {private String name;private int age;public Student(){}public Student(String name, int age){this.name = name;this.age = age;}public String getName(){return name;}public void setName(String name){this.name = name;}public int getAge(){return age;}public void setAge(int age){this.age = age;}public void sleep(){System.out.println("睡觉");}private void eat(String something){System.out.println("吃" + something);}public String toString(){return "Student [name=" + name + ", age=" + age + "]";}}
反射的作用
  • 获取一个类里面的所有信息,获取到之后,再执行其他的业务逻辑
  • 结合配置文件,动态地创建对象并调用方法
练习
保存信息

对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去

在这里插入图片描述

package 反射.src.myreflect5;import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;public class myReflectDemo5 {/**对于任意一个对象,都可以把对象的所有字段名和值,保存到文件中去。*/public static void main(String[] args) throws IllegalAccessException, IOException {Student student = new Student("Tom", 20, "Male", 175.4f, "Reading");Teacher teacher = new Teacher("Jane", 30000);// 保存Student对象到文件中saveObject(student);
//        saveObject(teacher);}//把对象里面所有的成员变量名和值保存到本地文件中public static void saveObject(Object object) throws IllegalAccessException, IOException {//1、获取字节码文件的对象Class clazz = object.getClass();//创建io流BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\word保存\\全栈技术开发\\reflection\\a.txt"));//2、获取类的成员变量Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);//获取到成员变量的名字String name = field.getName();//获取到成员变量的值Object o = field.get(object);System.out.println(name + ":" + o);//写出数据bw.write(name + ":" + o + "\n");bw.newLine();}bw.close();}}
name:Tom
age:20
gender:Male
height:175.4
hobby:Reading
name:Jane
salary:30000
package 反射.src.myreflect5;public class Student {private String name;private int age;private String gender;private float height;private String hobby;public Student(String name, int age, String gender, float height, String hobby) {this.name = name;this.age = age;this.gender = gender;this.height = height;this.hobby = hobby;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public float getHeight() {return height;}public void setHeight(float height) {this.height = height;}public String getHobby() {return hobby;}public void setHobby(String hobby) {this.hobby = hobby;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String toString() {return "Student [name=" + name + ", age=" + age + ", gender=" + gender + ", height=" + height + ", hobby=" + hobby + "]";}
}
利用反射动态地创建对象和运行方法
package 反射.src.myreflect6;import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;public class MyReflectDemo {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {/*** 反射可以跟配置文件结合的方式,动态地创建对象,并调用方法*///1、读取配置文件中的信息Properties prop = new Properties();FileInputStream fis = new FileInputStream("E:\\word保存\\全栈技术开发\\reflection\\prop.yml");prop.load(fis);fis.close();System.out.println(prop);//2、获取全类名和方法名String className = (String)prop.get("classname");String methodName = (String)prop.get("method");System.out.println(className);System.out.println(methodName);//3、利用反射创建对象并运行方法Class<?> clazz = Class.forName(className);//获取构造方法Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();Object o = declaredConstructor.newInstance();System.out.println(o);//获取成员方法并运行Method method = clazz.getDeclaredMethod(methodName);method.setAccessible(true);method.invoke(o);}}
package 反射.src.myreflect6;public class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public void study(){System.out.println("学生正在学习!");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}
package 反射.src.myreflect6;public class Teacher {private String name;private double salary;public Teacher(String name, double salary) {this.name = name;this.salary = salary;}public void teach() {System.out.println("老师正在教书!");}public String getName() {return name;}public double getSalary() {return salary;}public void setName(String name) {this.name = name;}public void setSalary(double salary) {this.salary = salary;}@Overridepublic String toString() {return "Teacher [name=" + name + ", salary=" + salary + "]";}}
classname: 反射.src.myreflect6.Student
method: study
总结

在这里插入图片描述

http://www.lryc.cn/news/605517.html

相关文章:

  • 将本地项目关联并推送到已有的 GitHub 仓库
  • 第13届蓝桥杯C++青少组中/高级组选拔赛2022年1月22日真题
  • 可计算存储(Computational Storage)与DPU(Data Processing Unit)的技术特点对比及实际应用场景分析
  • #C语言——学习攻略:深挖指针路线(五)--回调函数,qsort函数,qsort函数的模拟实现
  • axios封装对比
  • 《C#与.NET Core跨平台开发的融合架构与实践逻辑》
  • 编程语言Java——核心技术篇(六)解剖反射:性能的代价还是灵活性的福音?
  • 【[CSP-J 2022] 上升点列】
  • RabbitMQ 的死信队列完整指南 (With Spring Boot)
  • 从遮挡难题到精准测量:激光频率梳技术如何实现深孔 3D 轮廓的 2um 级重复精度?
  • Mac上优雅简单地使用Git:从入门到高效工作流
  • 05百融云策略引擎项目交付-laravel实战完整交付定义常量分文件配置-独立建立lib类处理-成功导出pdf-优雅草卓伊凡
  • LCM中间件入门(1):工作原理核心概念及Ubuntu环境下的C++实践
  • 【Debian】4-‌2 Gitea搭建
  • Git踩坑
  • windows服务器 maven 配置环境变量,验证maven环境变量是否配置成功
  • es的histogram直方图聚合和terms分组聚合
  • Ubuntu/Debian 搭建 Nginx RTMP 服务器全攻略
  • [Broken IOS] 配置CLI | 终端用户界面TUI
  • 分布式ID方案(标记)
  • 【Linux】linux基础开发工具(二) 编译器gcc/g++、动静态库感性认识、自动化构建-make/Makefile
  • BasicAuthenticationFilter处理 HTTP 基本认证(Basic Authentication)的核心过滤器详解
  • 打破数据质量瓶颈:用n8n实现30秒专业数据质量报告自动化
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | LiveUserFilter(实时用户过滤组件)
  • ensp安全策略实验
  • 【工具】NVM完全指南:Node.js版本管理工具的安装与使用详解
  • 嵌入式仿真教学的革新力量:深圳航天科技创新研究院引领高效学习新时代
  • 【n8n】如何跟着AI学习n8n【03】:HTTPRequest节点、Webhook节点、SMTP节点、mysql节点
  • 从“碎片化”到“完美重组”:IP报文的分片艺术
  • mysql笔记02:DML插入、更新、删除数据