Java的反射机制 及 操作Class类
反射
一、静态语言和动态语言
1.1 静态语言
静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,运行时结构不可变。
例如:C、C++、Java、Delphi、C#等。
1.2 动态语言
动态语言是在运行时可以改变结构的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
例如:PHP、Ruby、Python、SQL、JavaScript等。
Java不是动态语言,但因为反射,Java可以称之为“准动态语言”。
二、反射机制
2.1 定义
- Java反射机制是在运行状态中
- 对任意一个类,都能够知道这个类的所有属性和方法
- 对任意一个对象,都能够调用这个对象的任意方法和属性
- 这种动态获取信息以及动态调用对象方法的功能,称为 Java 语言的反射机制,是 Java 被视为动态语言的关键。
反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
2.2 用途
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时获取所需的私有成员变量和方法
- 在运行时处理注解
- 生成动态代理
2.3 优缺点
优点:可以实现动态创建对象和编译,体现出很大的灵活性
缺点:对性能有影响。
2.4 反射的使用
通过反射获取类的Class对象:
Class.forName(包名)
获得Class对象- 一个类在内存中只有一个Class对象
- 一个类被加载后,类的整个结构都会被封装在Class对象中
public class Test {public static void main(String[] args) throws ClassNotFoundException {Class c1 = Class.forName("cn.edu.scau.reflection.User");Class c2 = Class.forName("cn.edu.scau.reflection.User");System.out.println(c1);System.out.println(c1 == c2);// 一个类在内存中只有一个Class对象,因此输出true}
}class User {private String name;private int age;// 省略构造方法// 省略getter、setter方法// 省略toString方法
}
三、Class类
3.1 定义
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个加载的类在 JVM 中只会有一个Class实例
- 一个Class对象对应的是一个加载到 JVM 中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成
- 通过Class可以完整地得到一个类中的所有被加载的结构
- Class类是Reflection的根源,针对任何想动态加载、运行的类,唯有先获得相应的Class对象
3.2 获取Class类的常用方法
已知具体的类,通过类的
class
属性获取,该方法安全性和可靠性最高Class clazz = Person.class;
已知某个类的实例,调用该类的
getClass()
方法获取Class对象Person person = new Person(); Class clazz = person.getClass();
已知一个类的全名和路径,可通过Class类的静态方法
forName()
获取,可能抛出ClassNotFoundException异常public class Test {public static void main(String[] args) throws ClassNotFoundException {Class clazz = Class.forName("cn.edu.scau.reflection.Person");} }
基本内置类型的包装类都有一个Type属性
Class type = Integer.TYPE;
获得父类类型的Class对象
public class Test {public static void main(String[] args) throws ClassNotFoundException {Student student = new Student();Class clazz = student.getClass();Class superclass = clazz.getSuperclass();System.out.println(superclass);// 输出:class cn.edu.scau.reflection.Person} }class Person {}class Student extends Person{}
3.3 哪些类型可以有Class对象
- class:外部类,成员(成员内部类、静态内部类),局部内部类,匿名内部类
- interface:接口
- []:数组
- enum:枚举
- annotation:注解@interface
- primitive type:基本数据类型
- void
Class c1 = Object.class; //类
Class c2 = Runnable.class; //接口
Class c3 = String[].class; //数组
Class c4 = int[][].class; //二维数组
Class c5 = ElementType.class; //枚举
Class c6 = Override.class; //注解
Class c7 = Integer.class; //基本数据类型
Class c8 = void.class; //void
Class c9 = Class.class; //Class
四、获取Class对象信息
获取Class对象
Class clazz = Class.forName("cn.edu.scau.reflection.User");
获取类的名字
System.out.println(clazz.getName()); // 包名 + 类名 System.out.println(clazz.getSimpleName()); // 类名
获取类的属性
// 本类 + 父类 + public Field[] fields = clazz.getFields(); for (Field field : fields) {System.out.println(field); }// 本类 + 所有(public + private + proteced) Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) {System.out.println(declaredField); }
获取指定属性
// 本类 + 父类 + public Field name = clazz.getField("name");// 本类 + 所有(public + private + proteced) Field age = clazz.getDeclaredField("age");System.out.println("name: " + name + "\nage: " + age);
获取类的方法
// 本类 + 父类 + public Method[] methods = clazz.getMethods(); for (Method method : methods) {System.out.println(method); }// 本类 + 所有(public + private + proteced) Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod); }
获取指定方法
// 本类 + 父类 + public Method getName = clazz.getMethod("getName"); // 需要传入数据类型的class文件 Method setAge = clazz.getMethod("setAge", int.class); System.out.println(getName); System.out.println(setAge);// 本类 + 所有(public + private + proteced) // clazz.getDeclaredMethod()
获取类的构造器
// 本类 + 父类 + public Constructor[] constructors = clazz.getConstructors(); for (Constructor constructor : constructors) {System.out.println(constructor); }// 本类 + 所有(public + private + proteced) Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor); }
获取指定构造器
Constructor constructor = clazz.getConstructor(String.class, int.class); System.out.println(constructor);
五、调用运行时类的指定结构
5.1 创建对象
- 本质是调用无参构造器,并且要有访问权限,不能是私有构造器
- 如果没有无参构造则报错
Class clazz = Class.forName("cn.edu.scau.reflection.User");
User user = (User) clazz.newInstance();
- 通过有参构造器也可以创建对象
- 通过Class的
getConstructor()
方法获取构造器 - 向构造器中传入有参构造器的参数,实例化构造器
Constructor constructor = clazz.getConstructor(String.class, int.class);
User user = (User) constructor.newInstance("冬", 18);
5.2 调用方法
- 通过反射调用方法
- 获取方法后调用
invoke()
方法激活,传递(对象,方法值)
Method setName = clazz.getMethod("setName", String.class);
setName.invoke(user,"冬"); // 激活,传递(对象,方法值)
System.out.println(user.getName());
5.3 操作属性
- 设置
setAccessible()
方法 - 方法、属性、构造器 都有
setAccessible()
方法 setAccessible()
是启动和禁用访问安全的开关,如果设置为true,则可以访问private修饰的方法- 如果反射使用得多的话,可以开启
Field age = clazz.getDeclaredField("age");
age.setAccessible(true); // 关闭程序的安全权限、获取私有属性或者方法
age.set(user,18); // 设置(对象,属性值)
System.out.println(user.getAge());
六、使用反射操作注解
编写注解,一个作用在类上,一个作用在属性上
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface ClassAnno {String value(); }@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldAnno {String value(); }
编写实体类,并为实体类得属性和方法添加注解
作用在类上得注解表示User的身份
作用在属性上的注解分别是对应的值
@ClassAnno("学生") public class UserDemo {@FieldAnno("冬")String name;@FieldAnno("18")int age;public UserDemo() {}public UserDemo(String name, int age) {this.name = name;this.age = age;}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;} }
编写测试类
使用
getAnnotation()
方法可以获取注解再使用注解
.value()
方法可以获取该注解的值public class TestDemo {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {Class clazz = Class.forName("cn.edu.scau.reflection.UserDemo");ClassAnno classAnno = (ClassAnno) clazz.getAnnotation(ClassAnno.class);String classValue = classAnno.value();System.out.println("你的身份是:" + classValue);Field name = clazz.getDeclaredField("name");FieldAnno nameAnno = name.getAnnotation(FieldAnno.class);String nameValue = nameAnno.value();System.out.println("你的名字:" + nameValue);Field age = clazz.getDeclaredField("age");FieldAnno ageAnno = age.getAnnotation(FieldAnno.class);String ageValue = ageAnno.value();System.out.println("你的年龄:" + ageValue);} }
Java的反射机制 及 操作Class类相关推荐
- Java的反射机制 —— 类的镜子
Java的反射机制 -- 类的镜子 文章目录 Java的反射机制 -- 类的镜子 一.反射机制的原理 1.1.什么是反射? 1.2.反射机制的实现 1.3.获取类的Class对象的途径 1.4.运行时 ...
- 深入理解Java Class反射机制
本篇主要是深入对Java中的Class对象进行分析,这对后续深入理解反射技术非常重要,这篇有点偏向内功类文章. 深入理解Class对象 RRTI的概念以及Class对象作用 认识Class对象之前,先 ...
- Java的反射机制 工厂模式综合讲解【转载自51CTO】
2019独角兽企业重金招聘Python工程师标准>>> Java的反射机制 工厂模式综合讲解 1.什么叫反射 Java.lang.reflect包下 正常情况下我们可以通过类实例化一 ...
- java原理—反射机制
http://www.cnblogs.com/forlina/archive/2011/06/21/2085849.html 一.什么是反射: 反射的概念是由Smith在1982年首次提出的,主要是指 ...
- 学习:java原理—反射机制
一.什么是反射: 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提 出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...
- Java基础-反射机制
目录 1.反射机制概述 2.获取class的三种方式 2.1.Class.forName()方式 2.2.obj.getClass()方式 2.3..class方式 3.通过反射实例化对象 4.通过读 ...
- Java —— Reflect反射机制
JAVA反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java的反射机制. ...
- 什么是Java的反射机制
Java反射机制是Java的特点,是框架实现的基础,百度结果: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这 ...
- 什么是Java的反射机制?
Java 的反射机制是使其具有动态特性的非常关键的一种机制,也是在JavaBean 中广泛应用的一种特性. 运用JavaBean 的最常见的问题是:根据指定的类名,类字段名和所对应的数据,得到该类的实 ...
最新文章
- Live Writer 在oschina上的代码高亮插件推荐
- 巡回沙龙_美浮特全国巡回沙龙第一期结束撒花!
- javascript设计模式-学习笔记
- EOSIO:EOSIO最新版1.4.0创建测试账户
- Hive 之 分析窗口函数
- Spring容器创建流程(8)初始化bean
- SIGIR 2020 | 知识图谱上推荐推理的模仿学习框架
- git ssh配置完后拉取代码_二、windows下使用git拉取github上的项目(通过设置ssh key方式)...
- 新建文件夹god.html,win10 新建文件夹没有了
- Access入门之索引查询
- 计算机号密码保护,如何使用BIOS或UEFI密码保护计算机 | MOS86
- 【Python-二分法-查找重复值】
- vue将文件图片批量打包下载zip
- java图片合成_Java图片处理(一)图片合成
- 安装配置ELK、安装配置ElasticSearch7.13、安装配置Kibana7.13、安装配置Logstash7.13、ElasticSearch7.13安装中文分词器
- asp.net 获得根文件夹在服务器上物理路径,asp.net获取网站目录物理路径示例
- 性能摄影设计续航怎么选?荣耀Play4T系列全都要!
- 微信截图不能截微信界面
- Windows 10 C:/Users/用户名/AppData里面的文件选择性清空
- 我的世界服务器修改spawn,编辑“命令/spawnpoint” - Minecraft Wiki,最详细的官方我的世界百科...
热门文章
- java会议管理系统_基于jsp的会议管理系统-JavaEE实现会议管理系统 - java项目源码...
- 大数据(Big data)
- 软件设计与体系结构(第二版)部分习题
- BuChain 介绍:视屏讲解
- RGB与LAB优化互转
- OSChina 周一乱弹 —— 你老婆嘛时候再出差?
- 32位程序使用超过4G的内存 实例
- 企业建站之是自招开发人员组团队还是外包?软件外包开发靠谱吗?
- Expo大作战(三十一)--expo sdk api之Payments(expo中的支付),翻译这篇文章傻逼了,完全不符合国内用户,我只负责翻译大家可以略过!...
- SSS1700B1-QCC QFN36原理图|3S1700 USB 声卡|Typec拓展坞声卡