最新要闻
- 比亚迪海鸥实车现身 网友:买早了 8万元绝对卖爆
- 打破Steam Deck 12周霸榜!《霍格沃茨之遗》登顶Steam周销榜
- 今日精选:老人无证驾驶无牌三轮车逆行被撞还被罚 网友:建议全国推广
- 【世界快播报】专家称成年人有权做个废物!网友:反而更激励了我
- 天天亮点!00后平均期望薪资超7K 月薪高于一切:曾被痛批不应为钱选择工作
- 微头条丨校长用张颂文成名故事激励学生:日复一日打磨自己才是人生征程
- 2022年中国汽车销量排名:上汽第一 比亚迪增速太猛
- 当前头条:真维斯官方清仓:连帽夹克69.9元、棒球服夹克89.9元
- 当前热讯:Switch超级大作 《塞尔达传说:王国之泪》泄露:极具魅力
- 天天快消息!腾讯开办职业技能培训学校 网友:教打游戏吗?
- yy直播是个什么样的平台?YY礼包怎么领取?
- 社稷的原意是指什么?社稷中的社和稷是什么意思?
- 中国五大淡水湖是哪五个?中国五大淡水湖从大到小排列
- 上海世博会的吉祥物叫什么名字?上海世博会的意义有哪些?
- 卢知宣是哪个组合的歌手?卢知宣个人资料
- 世界热推荐:佳能一口气推四款新品:EOS R8、EOS R50都来了
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
java注解与反射详解
一、注解篇
1.1、注解的基本概念
注解:一种代码级别的说明,它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次;它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释.
要将注解(annotation)和注释(commnet)分开,注释是给人看的,机器不会执行,而注解主要是是给机器“看的”;
(资料图片)
比如多线程中重写run()方法,会有一个
@Override
注解,该注解一是给人说明这个方式是一个重写方法,而是给机器做检查(如果你重写的方法名等不正确会报错!)注解和反射是许多java框架的底层,因此必须学好!
作用:
- 编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
- 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
- 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
总结:注解就是java代码的一种,可以认为是一种类型,并且主要是给机器看的
注解格式
@<注解名>[(参数)]# @Override# @SuppressWarning("all")
1.2、java内置注解
1.2.1、作用在代码的注解
①、@Override
作用: 检查该方法是否是重写方法;如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误.
代码演示:
package kuang.annotation.lesson1;/** * 测试Override的案例 */public class TestOverride { @Override public String tostring() { // 重写的toString方法,这里将S改为小写会报错,因为Object中没有该方法 return "TestOverride{}"; } public static void main(String[] args) { }}
效果展示:
上方代码将
toString
方法的S
改为了小写,@Overside
检查后发现父类(Object类)中没有该方法,会发生编译错误
②、@Deprecated
作用:标记过时方法,标明该方法在该版本JDK过时或有更好的替代;如果使用该方法,会报编译警告,但不影响运行。
代码演示:
package kuang.annotation.lesson1;/** * 测试Deprecated的演示 */public class TestDeprecated extends Thread { /** * 参数since,表示已注解的API元素已被弃用的版本 * 参数forRemoval,元素表示注解的API素在将来的版本中是否被删除 * 这两个参数是java9之后新增的,平时可以不用 */ @Deprecated(since = "9",forRemoval = true) // 使用废弃注解标明该方法已经不推荐使用 public static void test() { System.out.println("废弃注解测试"); } public static void main(String[] args) { test(); // 废弃方法在同一个类中,会直接标明该方法 new Thread("小明").stop(); // 通过继承等方式调用被弃用方法,会有个横线划掉方法 }}
效果展示
③、@SuppressWarnings
作用:指示编译器去忽略注解中声明的警告,可以使用参数标明镇压警告的对象,可以是构造器、方法、类等
代码演示:
package kuang.annotation.lesson1;/** * 测试镇压警告注解的demo */@SuppressWarnings("all") // 使用镇压警告后,idea不会提示警告代码,并且代码在编译时,jvm也会包容警告public class TestSuppressWarning { public static void main(String[] args) { // 未使用的变量发生警告 int a; int c; int[] array = new int[1024]; System.out.println(1 == 1.2); // 警告 }}
效果展示:
idea没有提示警告代码
1.2.2、元注解
元注解(meta-annotation),就是负责注解其他注解的注解,套娃滴干活
元注解
@Target
:用来标明注解的使用范围@Retention
:指定其所修饰的注解的保留策略,保留策略有三个:SOURCE(源码级)、CLASS(字节码级)、RUNTIME(运行时级),最用范围依次变大@Document
:该注解是一个标记注解,用于指示一个注解将被文档化@Inherited
:该注解使父类的注解能被其子类继承@Repeatable
:Java 8 开始支持,标识某注解可以在同一个声明上使用多次、@FunctionalInterface
:Java 8 开始支持,标识一个匿名函数或函数式接口@SafeVarargs
: Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告
代码演示
package kuang.annotation.lesson1;import java.lang.annotation.*;public class TestMetaAnnotation { public static void main(String[] args) { } @Target(ElementType.METHOD) // 注解应用于方法上 @Retention(value = RetentionPolicy.RUNTIME) // 表示该注解一直到运行时有效 @Documented // 表示将注解生成在javaDoc中,不加则在javaDoc中不生成 @Inherited // 子类可以继承父类的注解 @interface myAnnotation { // 我定义的注解 }}
1.3、自定义注解
规范
- 使用关键字
@interface <注解名>
定义注解 - 注解体中可以包含配置参数,配置参数的形式为
<基本类型> 配置参数名()
,必须加上括号,类似一个方法 - 配置参数可以有多个,且名称自定义,可以使用
default
关键字给配置参数加上默认值 - 带配置参数的注解被引用时,参数部分必须以键值对形式写出来,有默认值的可以不写(也可以写,就是覆盖掉默认值),没有默认值的配置参数必须写上值
- 单个配置参数可以使用默认参数名
value
,该名称在注解被时引用时可以省略
- 使用关键字
代码演示
注解定义部分
package kuang.annotation.lesson1;import java.lang.annotation.*;/** * 注解定义: * 1.@interface关键字来定义注解 * 2.注解体中可以包含配置参数 * 3.配置参数需要有类型和配置参数名,参数类型都是基本数据类型,参数名类似方法名,需要用() * 4.自定义注解一般需要使用元注解,如@Target等来修饰,但可有可无 */@Target(ElementType.METHOD) // 表示注解的使用范围是方法,如果不加该注解则自定义注解可以应用在任何地方@Retention(RetentionPolicy.RUNTIME) // 不写该注解默认保留策略为CLASS级别public @interface MyAnnotation { String name() default "张三"; // 配置参数名为name,类型为String int age() default 0; String[] school() default {"北大","清华"}; // default可以给配置参数带上默认值 int id(); // 不带默认值,在该注解被引用时,必须显式写上}@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documented@interface MyAnno2 { // 单个配置参数,可以只用默认的参数名->value,默认参数名在注解引用时可以不写出 // 见SuppressWarning注解,它只含有一个单个的配置参数,且使用默认的配置参数名value,在注解被引用时,可以省略默认参数名 String value();}
引用部分
package kuang.annotation.lesson1;/** * 测试自定义注解的demo */public class TestMyAnnotation { // 自定义配置名称的注解,在写入参数时必须使用键值对形式 // 这里配置参数name有默认值,不写的话,这里也不会报错 // 但不带默认值必须显式写出来,即这里的id @MyAnnotation(age = 18,school = {"家里蹲"},id = 2022) public void test01(String name, int age, String[] school, int id) { System.out.println("自定义注解的测试"); } @MyAnno2("hello") // 默认参数名value的注解在被引用时,可以省略参数名 public void test02() { }}
二、反射篇
2.1、反射的基本概念
2.1.1、引入
动态语言:在运行时代码可以根据某些条件改变自身结构,比如新的方法、对象、代码的引入,已有的代码可以在结构上发生变化;常见的动态语言比如:JS、PHP、Python等,可以发现他们都是解释型语言,这类语言最大的特点就是在运行时才确定某些代码的性质,比如数据类型等,并且运行时可以改变自身结构,比如PHP和JS可以使用执行函数eval()来执行一些非代码的字符串等
静态语言:运行时结构不可改变的语言,比如C/C++、java;常见的类C语言都是静态语言,这类语言最大的特点就是运行前必须规定代码的性质,比如必须规定一个变量的数据类型,否则连编译都无法通过,并且已一个类在运行时无法获取其内部信息
反射机制:让程序可以访问、检测和修改它本身状态或行为;java反射机制是指在Java程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法。这种动态获取类的内容以及动态调用对象的方法称为反射机制;
反射机制的核心:能够分析类的能力是java反射机制的核心,我们可以在运行时获得程序或者程序集中每个类型的成员已经成员的信息
2.1.2、应用
java反射机制主要提供了以下功能:
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
- 生成动态代理。
- 获取泛型信息。
- 获取注解信息。
2.1.3 韩顺平反射补充
2.1.3.1 反射机制原理图
解释:某类的源码通过javac编译成jvm字节码,我们通常在使用时通过new来将类实例化为对象,并通过对象调用成员方法等;在实例化为对象前,该类首先要被类加载器ClassLoader加载至堆区,并在堆区创建该类的Class类对象,该Class类对象包含被加载类的所有信息,且无论被加载类实例化出多少对象,它有且只有一个Class类对象;实例化出的被加载类对象记录着自己属于哪一个Class类对象;反射机制即是通过Class类对象来直接创建对象、操作属性等
2.1.3.2 反射简单应用举例
需求
源码实现
配置文件
re.properties
classfullpath = com.hspedu.Catmethod = hi
Cat类
package com.hspedu;public class Cat { private String name = "tomcat"; public void hi() { System.out.println("hi, i am " + name); }}
ReflectionQuestion类
package com.hspedu.reflection.question;import com.hspedu.Cat;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.nio.file.Files;import java.nio.file.Paths;import java.util.Properties;/** * 韩java 01-02 */public class ReflectionQuestion { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // 1、传统方法,new出类的实例化对象 Cat cat = new Cat(); cat.hi(); System.out.println("_________________________"); // 2、通过I/O流的Properties类读出配置文件 Properties properties = new Properties(); properties.load(Files.newInputStream(Paths.get("src\\re.properties"))); // 获取配置文件键值对的值 String classpath = properties.get("classfullpath").toString(); String method = properties.get("method").toString(); System.out.println(classpath); System.out.println(method); System.out.println("_____________________________"); // 3、反射机制 Class> cls = Class.forName(classpath); // 加载Cat类并范围其唯一的Class类对象 Object o = cls.newInstance(); // 通过Class类对象cls,得到加载类的实例对象 //System.out.println(o.getClass()); // 测试o真正的类型是否为Cat类 Method method1 = cls.getMethod(method);// 通过cls返回加载类的method的方法对象,即将Cat的hi方法通过对象形式返回并调用 method1.invoke(o); // 通过方法对象援引加载类的实例对象来调用方法 }}
当Cat类中新增了一个方法cry,我们仅需通过修改配置文件的method值即可,而不用修改源码
修改的Cat类
package com.hspedu;public class Cat { private String name = "tomcat"; public void hi() { System.out.println("hi, i am " + name); } // 新增方法 public void cry() { System.out.println("tomcat is cry"); }}
修改的配置文件
classfullpath = com.hspedu.Catmethod = cry // x
ReflectionQuestion类的修改
- 通过new的传统方法
// 1、传统方法,new出类的实例化对象Cat cat = new Cat();// cat.hi(); --> 修改源码为cat.cry();System.out.println("_________________________");
- 而反射机制不需要修改源码,仅需修改配置文件即可,符合ocp开闭原则(对修改封闭,对拓展开放)
2.2、反射的简单使用
2.2.1、获得反射对象
Java反射运行程序再执行期间借助
refelction API
获得任何类的内部信息,直接操作任意对象的内部属性及其方法反射对象获取方式:
获取方法 解释 Class.forName(<全类名>) 编译阶段,一般用配置文件中已知全类名信息 <类名>.class 加载阶段,一般用于参数传递 <实例化对象>.getClass() 运行阶段,已经有加载类的实例化对象 classLoader = <实例化对象>.getClass().getClassLoader()classLoader.loadClass(cls) 通过类加载器获取 <基本数据类型>.class 基本数据类型获取Class对象 <包装类>.TYPE 基本数据类型的包装类获取Class对象 加载完类后,会在内存中产生一个Class的对象,并且
一个类只有一个Class对象
,该Class对象包含整个类的完整结构,我们可以通过这个Class对象得到类的所有信息;这个Class对象就像一面镜子,通过镜子看到了类的结构,所以形象的称之为反射代码演示
package kuang.Reflection.lesson2;/** * 通过反射获得类的Class对象de体验 */public class TestObjectToClass { public static void main(String[] args) throws ClassNotFoundException { // 通过反射获得类的class对象 Class> c1 = Class.forName("kuang.Reflection.lesson2.TestObjectToClass"); System.out.println(c1); // 一个类在内存中只有一个Class对象 // 一个类被加载后类的整个结构都会被封装在Class对象中 Class> c2 = Class.forName("kuang.Reflection.lesson2.TestObjectToClass"); Class> c3 = Class.forName("kuang.Reflection.lesson2.TestObjectToClass"); Class> c4 = Class.forName("kuang.Reflection.lesson2.TestObjectToClass"); // 由hashcode相等可得,一个类在内存中只有一个Class对象 System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashCode()); }}/** * 实体类,pojo */class Person { String name; int age; int id; public Person() {} public Person(String name, int age, int id) { this.name = name; this.age = age; this.id = id; } 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 int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Person{" + "name="" + name + "\"" + ", age=" + age + ", id=" + id + "}"; }}
输出结果
2.2.2 韩顺平反射相关类补充(P4)
相关类及其作用
应用
package com.hspedu.reflection;import com.hspedu.Cat;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * 02韩顺平反射相关类,p4 */public class Reflection_P4 { public static void main(String[] args) throws Exception { // 01,反射相关类之Class类,表示某个加载类在内存中的Class对象,该Class对象有且只有一个 Class> aClass = Class.forName("com.hspedu.Cat"); // 和上方作用相同,都是返回对应的Class对象,不过下面这个是通过加载类的实例化对象逆向得到的 Cat cat = new Cat(); Class extends Cat> aClass1 = cat.getClass(); // 通过加载类的Class对象实例化出被加载类的对象 Object o = aClass.newInstance(); Cat cat1 = aClass1.newInstance(); // 这里直接指定为Cat类是因为它本身就是通过Cat的实例化对象逆向产生的 // 02,反射相关类之Method,创建某个加载类的成员方法的方法对象 Method hi = aClass.getMethod("hi"); // 得到Cat类的hi成员方法的方法对象 // 该方法对象援引加载类的实例化对象即可执行该方法,这也是反射之精妙所在 // 普通方式:实例化对象.成员方法 // 反射方式:成员方法对象.方法(实例化对象) hi.invoke(o); // 03,反射相关类之Field,创建加载类的成员属性的对象 Field ageField = aClass.getField("age"); // 该方式不能得到私有属性 System.out.println("age == " + ageField.get(o)); // 通过反射方式打印字段数据 // 04,反射相关类之Constructor,创建加载类的构造器对象 Constructor> constructor1 = aClass.getConstructor(); // 返回无参构造器 System.out.println("无参构造器:"+ constructor1); // 创建有参构造器对象,要注意getConstructor方法的参数是Class类型,通过int.class即可得到int的Class类对象 Constructor> constructor2 = aClass.getConstructor(int.class); System.out.println("有参构造器:" + constructor2); }}
输出截图
2.2.3 反射机制优化
反射机制优点:可以动态的创建和使用对象,是所有框架的底层
反射机制缺点:反射机制的执行手段基本是解释执行,且对加载类的字段、方法、构造器有可访问性检测(访问检查)
优化手段:在使用反射机制调用加载类的字段、方法、构造器时手动关闭访问检查
setAccessible(); // 传入参数为true时关闭访问检查// 使用方法举例Object o = aClass.newInstance();Method hi = aClass.getMethod("hi");hi.setAccessible(true); // 传入参数true···
2.3 认识Class类
2.3.1 Class类分析
Class类也是类,因此也继承Object类
Class不能通过new创建,它是由系统创建在堆区中的
某加载类的字节码二进制数据首先会通过类加载器CLassLoader的
loadClass()
方法生成该类的Class类对象(类加载机制),然后再实例化出对象;并且类加载过程在同一程序中只会进行依次,下一次实例化对象会直接使用已经在堆区生成的唯一个Class对象某个类的Class对象在内存中有且只有一个,并且类加载只进行一次
每个类的实例化对象记录着自己由哪个Class对象所生成
通过Class类对象可以得到一个类的完成结构
类的字节码二进制数据存放在方法区(类的元数据),类的Class类对象存放在堆区
代码印证第三条
package com.hspedu.reflection;import com.hspedu.Cat;/** * han _p6,反射机制之Class类 */public class Reflection_P6 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Cat cat = new Cat(); // 通过new实例化对象,Class对象已经生成在堆区 /*public Class> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); }*/ Cat cat1 = new Cat(); // 打断点调试,不会再执行loadClass来生成Class对象 // 通过反射机制创建类的实例化对象 Class> aClass1 = Class.forName("com.hspedu.Cat"); Class> aClass2 = Class.forName("com.hspedu.Cat"); // 哈希值相同,说明Class类对象相同,说明只有一个Class类对象 System.out.println(aClass1.hashCode()); System.out.println(aClass2.hashCode()); }}
2.3.2 Class常用方法
方法名 | 作用 |
---|---|
Class.forName(<加载类的全类名>) | 获得加载类的Class类对象Class> cls = Class.forName(classFullPath); |
cls.getClass() | 获取运行类型 |
cls.getPackage() | 获取包信息 |
cls.getName() | 获取全类名 |
cls.newInstance()》cls.getDeclaredConstructor().newInstance() | 通过反射创建对象(该方法再java9之后过时,添加下面的方式) |
cls.getFields() | 获取所有字段信息,返回字段集数组 |
package com.hspedu.reflection._Class;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;@SuppressWarnings("all")public class Class01_p7 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { String classFullPath = "com.hspedu.Car"; // 获取Car类的Class类对象 Class> cls = Class.forName(classFullPath); // 显示cls是哪个加载类的Class对象 System.out.println(cls); // 获得运行类型 System.out.println(cls.getClass()); // 获取包名 System.out.println(cls.getPackage().getName()); // 获取加载类的全类名 System.out.println(cls.getName()); // 通过反射创建对象 Object o = cls.getDeclaredConstructor().newInstance(); // 通过反射获取所有字段信息,获取所有方法等方式类似 Field[] fields = cls.getFields(); for(Field f : fields) { System.out.println(f.getName() + "==" + f.get(o)); } }}
2.4 动态和静态加载
区别:静态加载在程序编译阶段就将程序内所引用的资源全部加载进来,如果资源不存在则编译不通过;动态加载则是在程序运行阶段时,当程序中所引用的资源不存在时才会去加载,即使所引用资源不存在也可以通过编译阶段。
通过反射机制可以实现动态加载,即用时加载
代码示例:
package com.hspedu.reflection._Class;import java.lang.reflect.Method;import java.util.Scanner;/** * 静态加载和动态加载——p10 */public class ClassLoaderTest { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); System.out.println("请输入对应数字"); int num = scanner.nextInt(); switch (num) { case 1: // 通过反射实现动态加载,即使person不存在也可以通过编译 Class> person = Class.forName("Person"); Object o = person.newInstance(); Method hi = person.getMethod("hi"); hi.invoke(o); break; case 2: // 静态加载,当Car类不存在,编译不通过 // Car car = new Car(); // 通过javac命令编译,去掉注释编译不通过,因为是静态加载 System.out.println("2"); default: System.out.println("do nothing"); } }}
上述代码中,Person类不存在,但可以通过编译,说明反射是动态加载解释执行
2.5 反射爆破操作
即通过反射机制突破所访问对象的限定符,主要是针对私有属性无法直接获取的问题
2.5.1 属性
获取属性对象的两种方式:
// 方式1:cls.getField() // 只能获取public修饰的cls.getDeclaredFiled() // 可以获取所有属性,包括私有的
私有属性爆破方式
<属性对象>.setAccessible(true)
变量赋值方式
<属性对象>.set(o,<值>)// 如果是静态属性,o可以写为null
案例代码
Student类
package com.hspedu;public class Student { public String name; private int age; public static int num; @Override public String toString() { return "Person{" + "name="" + name + "\"" + ", age=" + age + "}"; }}
测试类
package com.hspedu.reflection;import java.lang.reflect.Field;/** * 通过反射爆破属性_p17 */public class ReflectAccessProperty { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class> stuClass = Class.forName("com.hspedu.Student"); Object o = stuClass.newInstance(); // 通过反射获取public属性,并设置值 Field name = stuClass.getField("name"); name.set(o,"张三"); // 通过反射获取私有属性,并设置值 Field age = stuClass.getDeclaredField("age"); age.setAccessible(true); // 私有属性爆破 age.set(o,18); // 通过反射获取static变量,并设置值 Field num = stuClass.getField("num"); num.set(null,1433223); System.out.println(o); }}
2.5.2 方法
获取方法对象的方式
cls.getMethod("<方法名>",[
.class···]) // 获取公有方法,xxx.class即参数类型的class对象,无参则不写cls.getDeclaredMethod("<方法名>", .class) // 获取所有方法 爆破:
m.setAccessible(true)
调用方法
m.invoke(o,<实参列表>); // 针对不同方法有不同返回值// 静态方法o可以写为null
案例代码
Student类
package com.hspedu;public class Student { public String name; private int age; public static int num; public String setNameAndPrint(String name) { this.name = name; return "名字是" + name; } private String setAgeAndPrint(int age) { this.age = age; return "年龄是" + age; } public static void hi(String person) { System.out.println("你好" + person); } @Override public String toString() { return "Person{" + "name="" + name + "\"" + ", age=" + age + "}"; }}
测试类
package com.hspedu.reflection;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class ReflectAccessMethod { public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { Class> stuClass = Class.forName("com.hspedu.Student"); Object o = stuClass.newInstance(); // 获取公有方法 Method name = stuClass.getMethod("setNameAndPrint", String.class); // 执行方法 Object returnName = name.invoke(o, "张三"); // 获取私有方法 Method age = stuClass.getDeclaredMethod("setAgeAndPrint", int.class); // 爆破私有限定符 age.setAccessible(true); // 执行方法 Object returnAge = age.invoke(o, 18); // 获取静态方法 Method hi = stuClass.getMethod("hi",String.class); // 执行方法 hi.invoke(null,"玛卡巴卡"); System.out.println(returnName); System.out.println(returnAge); }}
2.6 反射获取注解信息
注解依附于不同的Target,因此要根据注解位置的不同,创建不同的Class类对象
例如某注解是TYPE上的注解,依附于某个类,就要先创建该类的Class对象;依附于某字段属性上,就要在该类的Class对象的基础上创建Field对象
通过反射获取注解信息是许多框架的底层操作,也是学习myBatis等的知识点
案例代码
package com.hspedu.ReflectToAnno;import java.lang.annotation.Annotation;import java.lang.annotation.Target;import java.lang.reflect.Field;import java.util.Arrays;/** * 反射获取注解信息测试 */public class Test { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class> c = Class.forName("com.hspedu.ReflectToAnno.Person"); // 获取指定注解的value值 TableName table = c.getAnnotation(TableName.class); String v = table.value(); System.out.println("tableName is " + v); // 获得指定位置上的注解,这里获取Person类属性上的 Field name = c.getDeclaredField("name"); FieldInfo fieldInfo = name.getAnnotation(FieldInfo.class); System.out.println(fieldInfo.columnName()); System.out.println(fieldInfo.type()); System.out.println(fieldInfo.length()); // 获取注解上的注解信息 Class> aClass = Class.forName("com.hspedu.ReflectToAnno.FieldInfo"); Annotation[] annotations = aClass.getAnnotations(); for (Annotation a : annotations) { System.out.println(a); } Target target = aClass.getAnnotation(Target.class); System.out.println(Arrays.toString(target.value())); }}
java注解与反射详解
世界快看点丨ChatGPT可能的影响与机会
当前短讯!面试官:实现异步的20种方式,你知道几个?
比亚迪海鸥实车现身 网友:买早了 8万元绝对卖爆
打破Steam Deck 12周霸榜!《霍格沃茨之遗》登顶Steam周销榜
今日精选:老人无证驾驶无牌三轮车逆行被撞还被罚 网友:建议全国推广
【世界快播报】专家称成年人有权做个废物!网友:反而更激励了我
天天亮点!00后平均期望薪资超7K 月薪高于一切:曾被痛批不应为钱选择工作
天天微头条丨drools规则动态化实践
全球微动态丨idea引入外部maven项目(非压缩)方式
每日消息!Hugging News #0203: 3.3 MB 的文生图模型、RHLF 训练框架、手机上能跑的 Transformer
环球今日讯!跟着廖雪峰学python004
微头条丨校长用张颂文成名故事激励学生:日复一日打磨自己才是人生征程
2022年中国汽车销量排名:上汽第一 比亚迪增速太猛
当前头条:真维斯官方清仓:连帽夹克69.9元、棒球服夹克89.9元
当前热讯:Switch超级大作 《塞尔达传说:王国之泪》泄露:极具魅力
天天快消息!腾讯开办职业技能培训学校 网友:教打游戏吗?
显卡花屏一般是什么部件坏了?显卡花屏怎么解决?
gmail账号怎么注册?gmail账号停用怎么快速恢复使用?
libs是什么文件夹?libs文件夹可以删除吗?
win7如何共享打印机?win7怎么设置屏幕不休眠?
显卡风扇不转是什么原因?显卡风扇不转怎么解决?
yy直播是个什么样的平台?YY礼包怎么领取?
社稷的原意是指什么?社稷中的社和稷是什么意思?
世界百事通!Buu刷题
今头条!node中的fs模块和http模块的学习
世界观天下!项目实战:Qt终端命令模拟工具 v1.0.0(实时获取命令行输出,执行指令,模拟ctrl+c中止操作)
环球看热讯:C#判断IP地址是否正确
中国五大淡水湖是哪五个?中国五大淡水湖从大到小排列
上海世博会的吉祥物叫什么名字?上海世博会的意义有哪些?
卢知宣是哪个组合的歌手?卢知宣个人资料
世界热推荐:佳能一口气推四款新品:EOS R8、EOS R50都来了
爽口弹牙 喜得佳潮汕牛肉丸/牛筋丸19.9元/斤官方大促
今年以来最大震级!土耳其7.8级地震现场实拍:房屋倒塌满街狼藉
环球观天下!浙大美女老师火了 曾是羽毛球冠军 选课人数远超班级容量
环球今热点:旧手机被换菜刀女子开80公里赎回 内含资料太珍贵:型号是小米
NutUI 4.0 正式发布!
200M内存就能用 Win11极限精简版实测:C盘只需8GB空间
手机预装App无法卸载是对用户侵害!人大教授:侵犯消费者自主选择权
焦点速讯:男子礁石上钓鱼被海浪拍进石缝 出海垂钓别选偏僻海域
特斯拉辅助驾驶不“看路” 撞碎一地护栏!车主:跟平时不一样
6999元 惠普新款32寸4K显示器上架:配备雷电4 100W供电
俄罗斯杀毒软件卡巴斯基将推自研OS及应用商店:不兼容第三方系统
全球热议:要钱没用!比尔盖茨喊话马斯克做慈善家:我们财富都捐出去
中国游客抛弃日韩后!新西兰首发团26000元1分钟售罄:出境游全面开启
读Java实战(第二版)笔记02_行为参数化Lambda表达式
全球速讯:男子油锅炸元宵现场惨烈 发生自爆崩起半米高:科普为何会翻车
天天头条:中国探月四期全面推进:月球上寻找水源、科研站基本成型
【全球新视野】Intel Arc 750新驱动提升43%游戏性能!RTX 3060最大劲敌来了
【全球播资讯】day02-REST和SpringMVC映射请求数据
万元起步?苹果iPhone 16将推Ultra超旗舰 库克称果粉愿意花高价
存储卡/U盘提示要格式化?先恢复出数据再说
【全球新要闻】2600元的PCIe 5.0 SSD全球首测:读写双破10GB/s!但吵死了
邪恶、丑陋的互联网:你还敢发孩子的短视频吗?
记一次selenium爬取p站图片的经历
世界热门:丰田最新表态:纯电车不环保!
焦点短讯!谷歌家也没有余粮了:用旧的服务器不要扔 擦擦还能用2年
环球快看点丨路由架构(一)
每日精选:《三体》电视剧罗辑亮相 网友:袁华 是你吗?
环球快消息!连续两部当主演 《流浪地球3》中或没有吴京:如何复活很关键
全球要闻:web安全基础-文件上传(含部分upload-labs靶场通关)
世界资讯:谈刻意练习 Talking about deliberate pratise
新动态:Linux环境下:程序的链接, 装载和库[动态链接]
【全球新要闻】染发剂致癌吗?几十块和几百块的染发剂 究竟有啥区别?
全球快讯:等等党赚了:《仙剑奇侠传七》宣布将加入XGP服务
环球新动态:Gmail之父:有了ChatGPT 搜索引擎活不过两年 就像干掉黄页电话簿
每日焦点!操作系统篇 ———— 开篇[一]
全球最资讯丨ES6 简介(二)
量子通信网络里程碑 中国科大实现模式匹配量子密钥分发
男子将厕所改造成电竞房 网友:从此再也不怕“膀胱局”了
世界观速讯丨9 文件操作
当前速看:多国反对被无视 日本2030年前排放40万吨核污水入海
今日关注:“最强法务部”名不虚传:任天堂赢得Joy-Con手柄集体诉讼案
热门:iPhone 14系列官方降价引热议 网友:安卓厂商压力山大
【环球时快讯】Java实现动态数组(数据结构与算法)
【全球新要闻】推特创作者将获得广告分成:需要开通蓝V会员才有资格
一加Ace 2正面“全身照”首次亮相:超窄边框双曲屏
当前速看:高中生分班前磕头跪谢班主任:网友看后意见大!老师回应:给每人发了红包
【全球速看料】MAUI新生6.9-控件辅助功能①:动画Animation
集合框架
10 正则表达式应用
《流浪地球2》里的“硬核科技” 中国电信已经用上了
全球报道:超详细--redis在Linux环境搭建主从复制
当前视讯!ChatGPT将英伟达AI GPU变成黄金 后者股价飙升超40%
《狂飙》带火鱼干店 老板:微信加烦了!剧中原来是这一集
焦点报道:为什么 L1 正则化能做特征选择而 L2 正则化不能
Linux环境下:程序的链接, 装载和库[可执行文件的装载]
当前焦点!Edge新版增加内容推荐按钮:打开甚至不用点
今日报丨比亚迪1月销量:汉卖出1.22万辆 宋Plus继续火爆
当前头条:[数据结构] 哈希表 (开放寻址法+拉链法)
天天动态:车主展示特斯拉自动泊车入位 结果翻车:变成“自动撞车”
【天天速看料】价格暴降后特斯拉供不应求 马斯克:准备要涨了
热点评!迁移学习(HDAN)《Heuristic Domain Adaptation》
美团索命一问:一个SQL ,怎么分析加了哪些锁? 含4大场景、8个规则
宝能造车梦破碎:烧了80多亿元的观致 如今沦为法拍车
女孩4万多元的摩托 被男摩友加白糖报废!官方介入
读Java实战(第二版)笔记01_Java的变化
全球即时:柔软顺滑 古今男士平角裤3条到手29.9元
世界视讯!休闲百搭 361° 运动束脚裤立减140元:49元起清仓价
环球速看:冰火两重天!四川一地昼夜温差38.6℃ 专家揭秘真相