反射
利用反射调用它类中的属性和方法时,无视修饰符。
获取Class类的对象(三种方式)
- Class.forName(“全类名”) (推荐使用)
- 类名.class
- 对象.getClass()
反射获取构造方法
Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
Constructor类中用于创建对象的方法
T newInstance(Object... initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查,针对访问私有
反射小结
获取class对象
三种方式: Class.forName(“全类名”), 类名.class, 对象名.getClass()
获取里面的构造方法对象
getConstructor (Class<?>... parameterTypes)
getDeclaredConstructor (Class<?>... parameterTypes)
如果是public的,直接创建对象
newInstance(Object... initargs)
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean) 暴力反射
反射获取成员变量并使用
反射获取Field对象
Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象
获取成员变量并使用
* void set(Object obj,Object value) :给指定对象的成员变量赋值
* Object get(Object obj)返回指定对象的Field的值
反射获取Method对象
Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name,Class<?>... parameterTypes): 返回单个公共成员方法对象
Method getDeclaredMethod(String name,Class<?>... parameterTypes): 返回单个成员方法对象
反射利用Method对象运行方法
Object invoke(Object obj, Object... args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
新建一个实体类
package com.test.interceptor.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* (Student)实体类
*
* @author makejava
* @since 2023-06-17 22:06:09
*/
@Data
public class Student implements Serializable {
private static final long serialVersionUID = 533250288527593152L;
private String sId;
private String sName;
private String sBirth;
private String sSex;
private Student(String name) {
this.sName = name;
System.out.println("name的值:"+name);
System.out.println("private ... Student...有参构造方法");
}
public Student() {
System.out.println("public ... Student... 无参构造方法");
}
public Student(String name,int age) {
this.sName = name;
this.sBirth = age+"";
System.out.println("name的值:"+name +"age的值:"+age);
System.out.println("public ... Student ... 有参构造方法");
}
}
获取Class对象的三种方式以及通过构造方法创建对象
package com.test.interceptor.testClass;
import com.test.interceptor.domain.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 获取class对象的三种方式
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// Class类中的静态方法forName(“全类名”) 全类名=包名+类名 (推荐使用)
Class<?> clazz = Class.forName("com.test.interceptor.domain.Student");
// System.out.println(clazz);
// 通过class属性来获取
Class<Student> class2 = Student.class;
// System.out.println(class2);
// 通过对象的getClass()方法来获取class对象
// Student s = new Student();
// Class<? extends Student> class3 = s.getClass();
// System.out.println(class3);
// 获取Constructor对象
System.out.println("==================");
// method1();
// method2();
// method3();
// method4();
// method5();
// method6();
// methods7();
}
private static void methods7() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
// 获取一个私有的构造方法并创建对象
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 获取一个私有化的构造方法
Constructor<?> constructor = aClass.getDeclaredConstructor(String.class);
// 被private修饰的成员,不能直接使用的
// 如果用反射强行获取并使用,需要临时取消访问检查
constructor.setAccessible(true);
// 直接创建对象
Student student = (Student)constructor.newInstance("张三");
System.out.println(student);
}
private static void method6() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// 在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
Student student = (Student)aClass.newInstance();
System.out.println(student);
}
private static void method5() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
// Constructor类中用于创建对象的方法
// T newInstance(Object... initargs):根据指定的构造方法创建对象
// setAccessible(boolean flag):设置为true,表示取消访问检查
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 获取构造方法对象
Constructor<?> constructor = aClass.getConstructor(String.class, int.class);
Student student = (Student)constructor.newInstance("张三", 23);
System.out.println(student);
Constructor<?> constructor1 = aClass.getConstructor();
Student stu = (Student) constructor1.newInstance();
System.out.println(stu);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 返回单个构造方法对象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 返回单个公共构造方法对象 ()中一定要跟构造方法的形参一致
Constructor<?> constructor1 = aClass.getConstructor();
System.out.println(constructor1);
Constructor<?> constructor2 = aClass.getConstructor(String.class, int.class);
System.out.println(constructor2);
}
private static void method2() throws ClassNotFoundException {
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 返回所有构造方法对象的数组
Constructor<?>[] constructors = aClass.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
}
private static void method1() throws ClassNotFoundException {
Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 返回所有公共构造方法对象的数组
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
}
}
获取成员变量并使用
package com.test.interceptor.testClass;
import com.test.interceptor.domain.Stu;
import com.test.interceptor.domain.Student;
import java.lang.reflect.Field;
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
// method1();
// method2();
// method3();
// method4();
// method5();
// method6();
}
private static void method6() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
Field field = clazz.getDeclaredField("address");
// 取消访问检查,访问私有数据
field.setAccessible(true);
Stu student = (Stu)clazz.newInstance();
Object o = field.get(student);
System.out.println(o);
}
private static void method5() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
// 获取成员变量并使用
//* void set(Object obj,Object value) :给指定对象的成员变量赋值
//* Object get(Object obj)返回指定对象的Field的值
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
Field field = clazz.getField("name");
// 创建对象
Stu student = (Stu) clazz.newInstance();
// 给指定对象赋值
field.set(student,"wangwu");
System.out.println(student);
}
private static void method4() throws ClassNotFoundException, NoSuchFieldException {
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
//Field getDeclaredField(String name)返回单个成员变量对象
Field field = clazz.getDeclaredField("address");
System.out.println(field);
}
private static void method3() throws ClassNotFoundException, NoSuchFieldException {
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
// Field getField(String name) 返回单个公共成员变量对象
// 获取成员变量必须真实存在,public修饰的
Field name = clazz.getField("name");
System.out.println(name);
}
private static void method2() throws ClassNotFoundException {
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
// 返回所有成员变量对象的数组 Field[] getDeclaredFields()
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
}
private static void method1() throws ClassNotFoundException {
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
// 返回所有公共成员变量对象的数组 Field[] getFields()
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
}
}
反射获取对象的方法并使用,运行
package com.test.interceptor.testClass;
import com.test.interceptor.domain.Stu;
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 ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//反射获取Method对象
// method1();
// method2();
// method3();
// method4();
//反射利用Method对象运行方法
// Object invoke(Object obj, Object... args):运行方法
// 参数一:用obj对象调用该方法
// 参数二:调用方法的传递的参数(如果没有就不写)
// 返回值:方法的返回值(如果没有就不写)
// 获取class对象
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
// 获取里面的method对象
Method method = clazz.getMethod("function4", String.class);
// 运行对象
// 创建Student对象
Stu student = (Stu)clazz.newInstance();
Object result = method.invoke(student, "张三");
System.out.println(result);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {
// Method getDeclaredMethod(String name,Class<?>... parameterTypes): 返回单个成员方法对象
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
Method show = clazz.getDeclaredMethod("show");
System.out.println(show);
Method method = clazz.getDeclaredMethod("function2", String.class);
System.out.println(method);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {
// Method getMethod(String name,Class<?>... parameterTypes): 返回单个公共成员方法对象
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
Method method = clazz.getMethod("function1");
System.out.println(method);
Method function2 = clazz.getMethod("function2", String.class);
System.out.println(function2);
}
private static void method2() throws ClassNotFoundException {
// Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
private static void method1() throws ClassNotFoundException {
// Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}
BigDecimal的使用(加减乘除)
BigDecimal类的构造方法:
BigDecimal(double val) 参数为double(不推荐使用)
BigDecimal(String val) 参数为String(推荐使用)
public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) 除法
BigDecimal小结
1, BigDecimal是用来进行精确计算的
2,创建BigDecimal的对象,构造方法使用参数类型为字符串的。
3,四则运算中的除法,如果除不尽请使用divide的三个参数的方法。
代码示例:
BigDecimal divide = bd1.divide(参与运算的对象, 小数点后精确到多少位, 舍入模式);
参数1 ,表示参与运算的BigDecimal 对象。
参数2 ,表示小数点后面精确到多少位
参数3 ,舍入模式
BigDecimal.ROUND_UP 进一法 BigDecimal.ROUND_FLOOR 去尾法 BigDecimal.ROUND_HALF_UP 四舍五入
package com.test.interceptor.bigdecimal;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class mybigdecimal {
public static void main(String[] args) {
// Bigdecimal的初始化时用尽量用String,假如传的是浮点类型,会丢失精度。
// 如果想使用精确运算,那么请使用字符串的构造
// method1();
// methodAdd();
// methodSubtract();
// methodMutiply();
// methodDivide();
// methodDivicd1();
}
private static void methodDivicd1() {
// BigDecimal小结
//1, BigDecimal是用来进行精确计算的
//2,创建BigDecimal的对象,构造方法使用参数类型为字符串的。
//3,四则运算中的除法,如果除不尽请使用divide的三个参数的方法。
//代码示例:
// BigDecimal divide = bd1.divide(参与运算的对象, 小数点后精确到多少位, 舍入模式);
// 参数1 ,表示参与运算的BigDecimal 对象。
// 参数2 ,表示小数点后面精确到多少位
// 参数3 ,舍入模式
// BigDecimal.ROUND_UP 进一法 BigDecimal.ROUND_FLOOR 去尾法 BigDecimal.ROUND_HALF_UP 四舍五入
BigDecimal bd1 = new BigDecimal("0.3");
BigDecimal bd2 = new BigDecimal("4");
BigDecimal divide = bd1.divide(bd2, 2, RoundingMode.HALF_UP);
System.out.println(divide);
}
private static void methodDivide() {
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.3");
BigDecimal divide = bd1.divide(bd2, 2, RoundingMode.HALF_UP);
System.out.println(divide);
}
private static void methodMutiply() {
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal multiply = bd1.multiply(bd2);
System.out.println("乘以为" + multiply);
}
private static void methodSubtract() {
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal subtract = bd1.subtract(bd2);
System.out.println("差为" + subtract);
}
private static void methodAdd() {
// 如果想使用精确运算,那么请使用字符串的构造
// BigDecimal bd1 = new BigDecimal(0.1);
// BigDecimal bd2 = new BigDecimal(0.2);
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal add = bd1.add(bd2);
System.out.println(add);
}
// 构造方法
private static void method1() {
BigDecimal bigDecimal1 = new BigDecimal(10.0);
BigDecimal bigDecimal2 = new BigDecimal("0.3");
System.out.println(bigDecimal1);
System.out.println(bigDecimal2);
}
}
自定义注解
格式:
public @interface 注解名称 {
public 属性类型 属性名()default 默认值;
}
元注解:
**@Target** 指定了注解能在哪里使用(常用)
**@Retention** 可以理解为保留时间(生命周期)(常用)
@Inherited 表示修饰的自定义注解可以被子类继承
**@Documented** 表示该自定义注解,会出现在API文档里面。(常用)
自定义一个注解(练习三)
自定义一个注解:
package com.test.interceptor.customannotation.testanno2.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MySysLog {
String value() default "";
int age() default 18;
String[] array() default {};
}
定义一个切面类
package com.test.interceptor.customannotation.testanno2.aspect;
import com.test.interceptor.customannotation.testanno2.annotion.MySysLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class SystemLogAspect {
@Around("@annotation(mySysLog)")
public Object around(ProceedingJoinPoint point, MySysLog mySysLog) throws Throwable {
// // 获取执行签名信息
// Signature signature = point.getSignature();
// // 通过签名获取执行操作类型(接口名)
// String className = signature.getDeclaringTypeName();
// // 通过签名获取执行操作类型(方法名)
// String methodName = signature.getName();
System.out.println(mySysLog.age());
System.out.println(mySysLog.array()[0]);
// class名称,方法名,参数,返回值,执行时间
MethodSignature signature = (MethodSignature)point.getSignature();
// 获取执行目标方法上的注解对象
MySysLog annotation = signature.getMethod().getAnnotation(MySysLog.class);
System.out.println(annotation.array()[0]);
String className = point.getTarget().getClass().getName();
// String className1 = signature.getDeclaringTypeName();
// System.out.println(className1);
String methodName = signature.getName();
Object[] args = point.getArgs();
System.out.println(className+","+methodName+","+Arrays.toString(args));
return point.proceed();
}
}
controller层
package com.test.interceptor.customannotation.testanno2.controller;
import com.test.interceptor.customannotation.testanno2.service.AnnotationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AnnotationController {
@Autowired
private AnnotationService annotationService;
@RequestMapping("/")
public String testMyService() {
annotationService.testMyService();
return "ok...";
}
}
service层:
package com.test.interceptor.customannotation.testanno2.service;
public interface AnnotationService {
public void testMyService();
}
实习类:
package com.test.interceptor.customannotation.testanno2.service.impl;
import com.test.interceptor.customannotation.testanno2.annotion.MySysLog;
import com.test.interceptor.customannotation.testanno2.service.AnnotationService;
import org.springframework.stereotype.Service;
@Service
public class AnnotationServiceImpl implements AnnotationService {
@Override
@MySysLog(array = {"1"})
public void testMyService() {
System.out.println("对数据库。。。。。。");
}
}
在启动类上加上开启aop注解
@SpringBootApplication
@EnableAspectJAutoProxy
public class InterceptorApplication {
public static void main(String[] args) {
SpringApplication.run(InterceptorApplication.class, args);
}
}
加入依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
自定义一个注解(练习一)
package com.test.interceptor.customannotation.testanno;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// 表示Test这个注解的存活时间
@Retention(value = RetentionPolicy.RUNTIME)
public @interface anno {
}
=============================
package com.test.interceptor.customannotation.testanno;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class AnnoDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
// 通过反射获取UseTest类的字节码文件对象
Class<?> aClass = Class.forName("com.test.interceptor.customannotation.testanno.UseTest");
// 创建对象
UseTest useTest = (UseTest) aClass.newInstance();
// 通过反射获取这个类里面所有的方法对象
Method[] methods = aClass.getDeclaredMethods();
// 遍历数组,得到每一个方法对象
for (Method method : methods) {
// method表示每一个方法的对象
// isAnnotationPresent 判断当前方法是否有指定的注解,参数:注解的字节码文件对象,true 存在,false 不存在
if(method.isAnnotationPresent(anno.class)) {
method.invoke(useTest);
}
}
}
}
===================================
package com.test.interceptor.customannotation.testanno;
public class UseTest {
// 没有使用Test注解
public void show() {
System.out.println("UserTest... show...");
}
// 使用Test注解
@anno
public void method() {
System.out.println("UseTest... method.....");
}
@anno
public void function() {
System.out.println("UseTest...function.....");
}
}
练习2
package com.test.interceptor.customannotation.testanno1;
import java.lang.annotation.*;
//@Inherited // 指定该注解可以被继承
@Documented
@Retention(RetentionPolicy.RUNTIME) // 指定了该注解的存活时间
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE}) // 指定注解使用的位置(成员变量,类,方法上)
public @interface Anno {
}
==================================
package com.test.interceptor.customannotation.testanno1;
@Anno
public class Person {
}
=====================
package com.test.interceptor.customannotation.testanno1;
public class Student extends Person{
public void show() {
System.out.println("student...show...");
}
}
===============
package com.test.interceptor.customannotation.testanno1;
public class StudentDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 获取到student类的字节码文件对象
String className = "com.test.interceptor.customannotation.testanno1.Student";
Class<?> aClass = Class.forName(className);
// 获取注解
boolean result = aClass.isAnnotationPresent(Anno.class);
System.out.println(result);
}
}
实现注解的步骤
- 声明注解
- 添加注解
- 获取添加了注解的目标,通常使Class对象,Method对象,Field对象,还有Contructor对象,Parameter对象,Annotation对象等。
- 通过已知对象,获取Class对象
- 通过全类路径,获取Class对象
- 扫描包路径,获取Class对象
- 实现注解处理器,借助反射,获取注解对象,读取注解属性值,然后根据注解及属性值做相应处理。
// value
public String value();
// 定义一个基本类型的属性
int a() default 23;
// 定义一个String类型的属性
public String name() default "itheima";
// 定义一个Class类型的属性
public Class clazz() default Anno2.class;
// 定义一个注解类型的属性
public Anno2 anno() default @Anno2;
// 定义一个枚举类型的属性
public Season season() default Season.SPRING;
// 以上类型的一维数组
// int 类型 枚举类型
public int[] arr() default {1,2,3,4,5};
public Season[] seasons() default {Season.SPRING,Season.SUMMER};
https://www.bilibili.com/read/cv13282317