反射
利用反射调用它类中的属性和方法时,无视修饰符。
获取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 {@Autowiredprivate 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注解@annopublic void method() {System.out.println("UseTest... method.....");}@annopublic 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对象
- 实现注解处理器,借助反射,获取注解对象,读取注解属性值,然后根据注解及属性值做相应处理。
// valuepublic 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