java反射和java注解

📅 2026/8/4 19:57:41
java反射和java注解
反射框架设计的灵魂框架半成品软件。可以在框架的基础上进行软件开发简化编码反射通过Class类型的对象字节码文件对象来操作对应的.class文件。可以在程序运行过程中操作这些对象这就是java的反射机制如下图。java反射的好处和作用只说明一个问题就是可以在程序运行中操作对象反射的好处1. 可以在程序运行过程中操作这些对象。2. 可以解耦提高程序的可扩展性。反射的作用在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时判断任意一个类所具有的成员变量和方法通过反射设置可以调用 private在运行时调用任意一个对象的方法获取class对象的方式同一个字节码文件(*.class)在一次程序运行过程中只会被加载一次不论通过哪一种方式获取的Class对象都是同一个。packagecom.demo.reflectDemo;importlombok.AllArgsConstructor;importlombok.Getter;importlombok.NoArgsConstructor;GetterNoArgsConstructorAllArgsConstructorpublicclassStudent{privateStringname;publicvoidstudy(){System.out.println(好好学习);}}packagecom.demo.reflectDemo;publicclassReflectDemo{publicstaticvoidmain(String[]args)throwsClassNotFoundException,IllegalAccessException,InstantiationException{/** * 获取Class对象 */// 通过指定的字符串路径获取// 多用于配置文件将类名定义在配置文件中。读取文件加载类Class?aClassClass.forName(com.demo.reflectDemo.Student);// com.demo.reflectDemo.StudentSystem.out.println(aClass.getName());// 通过类名的属性class获取多用于参数的传递ClassStudentstudentClassStudent.class;// com.demo.reflectDemo.StudentSystem.out.println(studentClass.getName());// 通过对象的getClass()方法获取多用于对象的获取字节码的方式StudentlxnewStudent(lx);Class?extendsStudentaClass2lx.getClass();// com.demo.reflectDemo.StudentSystem.out.println(aClass2.getName());System.out.println();/** * * Class对象相关方法 */// 获得简单类名只是类名没有包StringsimpleNameaClass2.getSimpleName();// StudentSystem.out.println(simpleName);// 获取完整类名包含包名类名// com.demo.reflectDemo.StudentSystem.out.println(aClass2.getName());// 创建此 Class 对象所表示的类的一个新实例。// 要求类必须有public的无参数构造方法StudentstudentaClass2.newInstance();//com.demo.reflectDemo.Student1540e19dSystem.out.println(student);}}Constructor类Constructor是构造方法类类中的每一个构造方法都是Constructor的对象通过Constructor对象可以实例化对象。packagecom.demo.reflectDemo;importjava.lang.reflect.Constructor;importjava.lang.reflect.InvocationTargetException;publicclassReflectDemo{publicstaticvoidmain(String[]args)throwsClassNotFoundException,IllegalAccessException,InstantiationException,NoSuchMethodException,InvocationTargetException{System.out.println(Constructor类);// 根据参数类型获取构造方法对象只能获得public修饰的构造方法。// 如果不存在对应的构造方法则会抛出 java.lang.NoSuchMethodException 异常。Constructor?extendsStudentconstructoraClass2.getConstructor(String.class);// public com.demo.reflectDemo.Student(java.lang.String)System.out.println(constructor);// 根据参数类型获取构造方法对象包括private修饰的构造方法。// 如果不存在对应的构造方法则会抛出 java.lang.NoSuchMethodException 异常。Constructor?extendsStudentdeclaredConstructoraClass2.getDeclaredConstructor(String.class);// public com.demo.reflectDemo.Student(java.lang.String)System.out.println(declaredConstructor);// 获取所有的public修饰的构造方法Constructor?[]constructorsaClass2.getConstructors();for(Constructor?constructor1:constructors){// public com.demo.reflectDemo.Student()// public com.demo.reflectDemo.Student(java.lang.String)System.out.println(constructor1);}// 获取所有构造方法包括privat修饰的// Constructor[] getDeclaredConstructors()System.out.println(Constructor类中常用方法);Studentstudent1declaredConstructor.newInstance(zs);// zsSystem.out.println(student1.getName());// 在获取private构造方法时java会检查权限就获取不到private// 所以执行构造方法之前我们需要取消java语言的访问检查// void setAccessible(true)}}Method类Method是方法类类中的每一个方法都是Method的对象通过Method对象可以调用方法。// 根据方法名和参数类型获得一个方法对象只能是获取public修饰的MethodgetMethod(方法名,方法的参数类型...类型)// 根据方法名和参数类型获得一个方法对象包括private修饰的MethodgetDeclaredMethod(方法名,方法的参数类型...类型)// 获取所有的public修饰的成员方法包括父类中Method[]getMethods()// 获取当前类中所有的方法包含私有的不包括父类中Method[]getDeclaredMethods()// Method类中常用方法// 据参数args调用对象obj的该成员方法 如果objnull则表示该方法是静态方法Objectinvoke(Objectobj,Object...args)// 暴力反射设置为可以直接调用私有修饰的成员方法voidsetAccessible(booleanflag)案例packagecom.demo.reflectDemo;importjava.io.IOException;importjava.io.InputStream;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.Properties;publicclassReflectDemo2{publicstaticvoidmain(String[]args)throwsIOException,ClassNotFoundException,IllegalAccessException,InstantiationException,NoSuchMethodException,InvocationTargetException{// 可以创建任意类的对象可以执行任意方法// 前提不能改变该类的任何代码。// 1. 加载配置文件// 1.1 创建Properties对象PropertiespropertiesnewProperties();// 1.2 获取class目录下的配置文件ClassLoaderclassLoaderReflectDemo2.class.getClassLoader();InputStreaminputStreamclassLoader.getResourceAsStream(application.properties);properties.load(inputStream);// 2. 获取配置文件中定义的数据StringclassNameproperties.getProperty(class.name);StringmethodNameproperties.getProperty(class.method.name);// 3. 加载该类进内存Class?aClassClass.forName(className);// 4. 创建对象ObjectobjaClass.newInstance();// 5. 获取方法对象MethodmethodaClass.getMethod(methodName);// 6. 执行方法method.invoke(obj);// 好好学习}}注解注解概述定义注解Annotation也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性与类、 接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面用来对这些元素进行说明注释。作用分类生成文档通过代码里标识的注解生成文档【例如生成文档doc文档author用来标识作者名】代码分析跟踪代码依赖性实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量编译检查在编译时进行格式检查。如Override放在方法前如果你这个方法并不是覆盖了超类方法则编译时就能检查出【例如Override】自定义注解packagecom.demo.annotationDemo;// 定义格式// 注解本质上就是一个接口该接口默认继承Annotation接口publicinterfaceAnnotationDemo{}注解的属性属性的作用可以让用户在使用注解时传递参数让注解的功能更加强大。属性的格式格式1数据类型 属性名();格式2数据类型 属性名() default 默认值;packagecom.demo.annotationDemo;// 定义格式// 注解本质上就是一个接口该接口默认继承Annotation接口publicinterfaceAnnotationDemo{Stringname();// 姓名intage()default18;// 年龄Stringgender()default男;// 性别// 该注解就有了三个属性nameagegender}属性适用的数据类型八种基本数据类型int,float,boolean,byte,double,char,long,short)String类型Class类型枚举类型注解类型以上所有类型的一维数组注解使用的注意事项空注解可以直接使用一个注解只能在一个位置上使用一次一个位置上可以使用多个不同的注解如果属性有默认值可以不赋值没有默认值必须赋值如果一个注解中只有一个属性value那么赋值时可以省略属性名如果属性值是数组类型多个属性值使用{}单个属性值{}可以省略使用自定义注解packagecom.demo.annotationDemo;publicinterfaceBook{Stringvalue();doubleprice()default100;String[]authors();}packagecom.demo.annotationDemo;publicclassBookShelf{Book(valuezs,price998,authors{666,777})publicvoidshowBook(){}}特殊属性 value()当注解中只有一个属性且名称是value在使用注解时给value属性赋值可以直接给属性值无论value是单值元素还是数组类型。如果注解中除了value属性还有其他属性且至少有一个属性没有默认值则在使用注解给属性赋值时value属性名不能省略。BookpublicinterfaceBook{Stringvalue();// 书名 }BookpublicclassBookShelf{Book(西游记)publicvoidshowBook(){}}注解之元注解默认情况下注解可以用在任何地方比如类成员方法构造方法成员变量等地方。如果要限制注解的使用位置怎么办那就要学习一个新的知识点元注解。元注解之Target作用指明此注解用在哪个位置如果不写默认是任何地方都可以使用。可选的参数值在枚举类ElemenetType中包括TYPE 用在类,接口上FIELD用在成员变量上METHOD 用在方法上PARAMETER用在参数上CONSTRUCTOR用在构造方法上LOCAL_VARIABLE用在局部变量上元注解之Retention作用定义该注解的生命周期(有效范围)。可选的参数值在枚举类型RetentionPolicy中包括SOURCE注解只存在于Java源代码中编译生成的字节码文件中就不存在了。CLASS注解存在于Java源代码、编译以后的字节码文件中运行的时候内存中没有默认值。RUNTIME注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中程序可以通过反射获取该注解。元注解使用实例packagecom.example.demo;importjava.lang.annotation.ElementType;importjava.lang.annotation.Target;Target({ElementType.METHOD,ElementType.TYPE})interfaceStu{Stringname();}packagecom.example.demo;Stu(namejack)publicclassAnnotationDemo02{// 成员变量Stu(namelily)// 编译失败privateStringgender;// 成员方法Stu(namerose)publicvoidtest(){}// 构造方法Stu(namelucy)// 编译失败publicAnnotationDemo02(){}}注解解析通过Java技术获取注解数据的过程则称为注解解析与注解解析相关的接口Anontation所有注解类型的公共接口类似所有类的父类是ObjectAnnotatedElement定义了与注解解析相关的方法常用方法以下四个// 判断当前对象是否有指定的注解有则返回 true否则返回falsebooleanisAnnotationPresent(ClassannotationClass)// 获得当前对象上指定的注解对象TgetAnnotation(ClassTannotationClass)// 获得当前对象及其从父类上继承的所有的注解对象Annotation[]getAnnotations()// 获得当前对象上所有的注解对象不包括父类的Annotation[]getDeclaredAnnotations()获取注解数据的原理注解作用在那个成员上就通过反射获得该成员的对象来得到它的注解。如注解作用在方法上就通过方法(Method)对象得到它的注解// 得到方法对象Methodmethodclazz.getDeclaredMethod(方法名);// 根据注解名得到方法上的注解对象Bookbookmethod.getAnnotation(Book.class);如注解作用在类上就通过Class对象得到它的注解// 获得Class对象Classc类名.class;// 根据注解的Class获得使用在类上的注解对象Bookbookc.getAnnotation(Book.class);java常见注解SuppressWarnings作用SuppressWarnings注解用于告诉编译器在编译过程中忽略特定类型的警告信息。通过使用这个注解你可以指示编译器不要发出某些警告从而减少在编译时看到不相关的警告。这个注解的使用方式如下SuppressWarnings(value{警告类型1,警告类型2,...})或者更简洁地SuppressWarnings(警告类型)其中value参数是一个字符串数组用于指定要忽略的警告类型。这些警告类型可以是编译器定义的警告类型也可以是一些自定义的字符串value取值常见的警告类型包括all忽略所有类型的警告。unchecked忽略未经检查的警告通常在使用泛型时出现。deprecation忽略使用已过时的 API 的警告。rawtypes忽略使用不带泛型类型的原始类型的警告。unused忽略未使用的代码或变量的警告。restriction忽略使用了受限制的 API 的警告通常用于访问非公开或不稳定的 API。示例使用SuppressWarnings(unchecked)publicvoidmyMethod(){ListmyListnewArrayList();// 忽略未经检查的警告myList.add(Hello);}SuppressWarnings({rawtypes,deprecation})publicvoidmyOtherMethod(){DatedatenewDate();// 忽略使用了已过时和原始类型的警告}需要注意的是尽管可以使用 SuppressWarnings 来忽略警告但这并不是解决问题的最佳方法。更好的方式是通过代码的重构或调整来消除警告以确保代码的质量和可维护性。在使用 SuppressWarnings 时应当慎重考虑确保了解可能的风险和影响。PostConstructPostConstruct注解的方法在项目启动的时候执行这个方法也可以理解为在spring容器启动的时候执行可作为一些数据的常规化加载比如数据字典之类的。执行顺序Constructor Autowired PostConstruct正确的做法是我们多辛苦一些让客户满意有了以后的合同就有了钱我们就能活下去。员工应多贡献以提高收入改善生活。我们的一些干部处于幼稚状态没有工作能力习惯将矛盾转给公司这些干部不成熟应调整他们的岗位。任正非部分内容转载自https://blog.csdn.net/CNDN_Web/article/details/132454387https://blog.csdn.net/a1k2l45k/article/details/135476656https://new.qq.com/omn/20220321/20220321A00XM100.html?pgv_refaio2015ptlang2052