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

高级技术【Java】【反射】【注解】【动态代理】

高级特性

1.Junit

Junit单元测试框架:用于对方法进行测试

注意测试用例需要全面。并做断言测试:断言结果是否与预期结果一致。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.反射

反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等),是底层框架的通用技术

常见示例:
在这里插入图片描述

  • 获取类的信息,操作他们,获得类中的成员变量、方法、构造器等
  • 1.加载类,获取类的字节码:class对象
  • 2.获取类的构造器:Constructor对象
  • 3.获取类的成员变量: Field对象
  • 4.获取类的成员方法: Method对象

1.获取class对象

1.类名.class
Class c1 = 类名.class
2.调用静态方法:forName
public static Class forName(String package);
3.使用Object提供的方法
Class c3 = 对象.getClass();

package com.reflect.reflectDemo;import lombok.Data;public class reflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {//1.获取类本身: 类名.classClass c1 = Animal.class;//2.调用static方法:forNameClass c2 = Class.forName("com.reflect.reflectDemo.Animal");//3.使用object提供的getclass方法Animal a = new Animal();Class c3 = a.getClass();System.out.println(c1==c2); //true;System.out.println(c2==c3); //true}
}@Data
class Animal {private String name;private int age;}

2.获取各种成分

1.获取构造器
2.获取成员变量
3.获取成员方法


package com.reflect.reflectDemo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.junit.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class reflectDemo2 {public static void main(String[] args) throws Exception {Class c1 = Student.class;//获取构造器Constructor[] cs = c1.getDeclaredConstructors();  //拿到全部构造器for (Constructor c : cs) {System.out.println(c.getName() + "(" + c.getParameterCount() + ")");}//获取无参构造器Constructor con = c1.getDeclaredConstructor();//利用构造器创建对象con.setAccessible(true);//私有方法暴力攻破访问权限Student s = (Student) con.newInstance();System.out.println(s);//获取两个参数的构造器Constructor con1 = c1.getDeclaredConstructor(String.class, int.class);Student s1 = (Student) con1.newInstance("小明", 12); //关系反转,先得到构造器,通过给构造器传入参数从而创建对象System.out.println(s1);////////////////////////////////////获取成员变量Field f1 = c1.getDeclaredField("hobby");System.out.println(f1.getName() + "(" + f1.getType().getSimpleName() + ")");Field f2 = c1.getDeclaredField("age");System.out.println(f2.getName() + "(" + f2.getType().getSimpleName() + ")");//获取成员变量的目的依然是取值和赋值Student s2 = new Student("小红", 23);f1.setAccessible(true);f1.set(s2,"写作业");  //赋值System.out.println(s2);String hobby = (String) f1.get(s2);System.out.println(hobby);//获取成员方法的目的依然是调用方法Student s3 = new Student("小贝", 43);Method m1 = c1.getDeclaredMethod("study");System.out.println(m1.getName() + "(" + m1.getParameterCount() + ")");m1.setAccessible(true);Object res1 = m1.invoke(s3);  //唤醒对象s3的study方法执行,相当于s3.study(); -> 小贝学习System.out.println(res1); //res1表示方法的返回值Method m2 = c1.getDeclaredMethod("study", String.class);System.out.println(m2.getName() + "(" + m2.getParameterCount() + ")");Object res2 =  m2.invoke(s3, "小黄");System.out.println(res2);}
}@Dataclass  Student {@Getterprivate String name;private int age;private String hobby;public Student(String name, int age) {this.name = name;this.age = age;}private Student() {}public String study(String name) {System.out.println(name + "在学习");return "别打扰我学习";}private void study() {System.out.println(this.name + "学习");}
}

3.反射的作用

  • 1.得到类的全部成分,然后操作
  • 2.可以破坏封装性
  • 3.可以绕过泛型的约束
    通过获取class文件(运行时),此时的泛型已经被擦除了,不再受泛型的约束。
    再通过反射,获取class里面的方法,通过方法去操作对象,从而到达翻墙(绕过泛型约束)的目的。

反射的含义:之前是通过new创建对象,再通过对象去获取构造器、成员变量、方法。现在可以通过先加载类.class,获取到构造器之后,通过获取的构造器去创建对象。获取成员变量之后,给对象赋属性值

简易框架

  • 实现传入一个对象,将它的所有字段以及对应的值保存到文件中去

package com.reflect.reflectDemo;import lombok.Data;
import lombok.Getter;import java.io.*;
import java.lang.reflect.Field;public class Frame {public static void main(String[] args) throws Exception {Student1 s = new Student1();saveObject(s);Animal1 a = new Animal1();saveObject(a);}public static void saveObject(Object obj) throws Exception {OutputStream os = new FileOutputStream("object.txt", true);PrintStream ps = new PrintStream(os);//obj 可能是老师类,学生类//只有反射可以知道对象有多少个字段//1.获取class对象Class c = obj.getClass();//2.获取Class对象的所有字段Field[] fields = c.getDeclaredFields();String simpleName = obj.getClass().getSimpleName();ps.println("===============" + simpleName + "=============");//遍历字段for (Field field : fields) {//获取字段的值String fieldName = field.getName();field.setAccessible(true); //暴力反射Object fieldValue = field.get(obj) + "";//打印到文件中ps.println(fieldName + "=" + fieldValue);System.out.println(fieldName + "=" + fieldValue);}}
}@Data
class Animal1 {private String name;private int age;
}@Dataclass  Student1 {@Getterprivate String name;private int age;private String hobby;public Student1(String name, int age) {this.name = name;this.age = age;}public Student1() {}public String study(String name) {System.out.println(name + "在学习");return "别打扰我学习";}private void study() {System.out.println(this.name + "学习");}
}

3.注解

**注解就是Java代码中的特殊标记,比如: @Override、@Test

  • 作用是让其他程序根据注解信息来决定怎么执行程序
  • 注意:注解可以用在类上、构造器、方法、成员变量、参数等位置

1.自定义注解

自己定义注解
在这里插入图片描述

2.注解原理

本质是一个接口,继承了Anotation类
在这里插入图片描述
在这里插入图片描述

3.元注解

注解注解的注解
@Target
@Retention
在这里插入图片描述

@Target:被它标记的注解只能在指定的位置使用,可以使用逗号隔开声明多个位置
在这里插入图片描述
@Retention:约束注解的存活范围,一般为运行时(一直都在),否则没有意义
在这里插入图片描述

4.注解的解析

  • 判断类上、方法上、成员变量上是否存在注解,并把注解的内容解析出来。
    在这里插入图片描述

在这里插入图片描述

5.注解的应用场景

使用注解开发出一个简易的Junit框架

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


动态代理

形象展示:
在这里插入图片描述
在这里插入图片描述

示例:

package com.itheima.proxyDemo;import jdk.jfr.DataAmount;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class proxyDemo {public static void main(String[] args) {//目标:创建代理对象//1.准备一个明星对象:设计明星类Start start = new Start("章若楠");//2.为明星对象创建代理StartServer proxy = ProxyUtil.createProxy(start);proxy.sing("罗生门");System.out.println(proxy.dance());}
}@Data
@AllArgsConstructor
@NoArgsConstructor
class Start implements StartServer {private String name;@Overridepublic void sing(String name) {System.out.println(this.name + "在唱歌,歌名为:" + name);}@Overridepublic String dance() {System.out.println(this.name + "在跳舞");return "谢谢谢谢";}}class ProxyUtil {//创建一个明星对象的代理对象返回public static StartServer createProxy(Start start) {/*参数一:用于执行哪个类加载器去加载生成的代理类参数二:用于指定代理类需要实现的接口:明星类实现的接口,代理类就需要实现参数三:用于指定代理类需要如何去代理(代理需要做的事情)*/StartServer proxy = (StartServer) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),start.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();if ("sing".equals(methodName)) {System.out.println("准备话筒,收钱10万!");} else if ("dance".equals(methodName)) {System.out.println("准备跳舞场地,收钱100万!");}//真正干活(把真正的明星对象叫过来正式干活)//调用真正的明星对象来执行被代理的行为Object result = method.invoke(start, args);return result;}});return proxy;}
}interface StartServer {void sing(String name);String dance();
}

解决实际问题

在这里插入图片描述

  • 可以简化代理的对象的重复操作,代理对象只需要专心处理专门的任务即可
    示例:比如要分析方法的性能,需要对每个方法的执行时间进行统计,在方法内部写性能分析代码会显得重复并且导致业务逻辑不清晰
    那么可以将性能分析任务交给代理来做,使用代理测试每个方法的执行时间。
    在这里插入图片描述

*上述内容均来自黑马程序员B站视频的学习笔记以及截图,仅为学习交流,不作为商业用途,如有侵权,联系删除。

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

相关文章:

  • 复习博客:JVM
  • 【Project】ELK 7.17.16 日志分析系统部署
  • 阿里云平台使用的ack创建的pod与服务器中的MongoDB不在同一网段如何解决
  • 【图像处理基石】什么是相机的内外参数?
  • 单表查询-分页提前获取数据
  • 自动化与安全 - 将 Terraform 集成到 CI/CD
  • 安装pytorch(cpu版)
  • 电科金仓2025发布会,国产数据库的AI融合进化与智领未来
  • 【Lucene】SimScorer
  • 【Spring AI】Advisors API—顾问(即拦截器)
  • 轨迹优化 | 基于边界中间值问题(BIVP)的路径平滑求解器(附C++/Python仿真)
  • 6.String、StringBuffer、StringBuilder区别及使用场景
  • C++学习笔记(六:数组)
  • AI Agent与MCP Service技术进展结构化分析报告(2025Q2)
  • 解决win10下Vmware虚拟机在笔记本睡眠唤醒后ssh连接不上的问题
  • 项目研发进度安排
  • 音视频学习(四十二):H264帧间压缩技术
  • 【时时三省】(C语言基础)使用字符指针变量和字符数组的比较
  • Electron使用WebAssembly实现CRC-16 原理校验
  • Java 二叉树
  • C++11之右值引用与移动语义(提高效率)重要
  • 【Linux指南】Linux系统 -权限全面解析
  • Jetpack ViewModel LiveData:现代Android架构组件的核心力量
  • 病历数智化3分钟:AI重构医院数据价值链
  • AI+Python | 长时序植被遥感:动态·物候·变异归因·RSEI生态评估全流程[特殊字符]
  • C语言(20250718)
  • 车载电子电器架构 --- MCU信息安全相关措施
  • 基于springboot+vue+mysql的在线教育系统(源码+论文)
  • 深入详解随机森林在医学图像质量评估中的应用与实现细节
  • 网络编程Socket linux