Java SE 基础:反射

作者:小兔子脚
链接:https://zhuanlan.zhihu.com/p/25057658
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

反射(Reflection)被视为 动态语言的关键。

反射机制 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态的获取信息以及动态调用对象的方法的功能称为Java语言的反射机制。

加载完类后,在堆内存中会产生一个 Class 类型的对象(一个类只有一个Class对象),这个对象包含了完整的类的结构信息,而且这个Class 对象就像一面镜子,透过这个镜子可以看到类的完整结构,所以称之为“反射”。



反射相关的主要API :
》java.lang.Class : 代表一个类
》java.lang.reflect.Method : 代表类的方法
》java.lang.reflect.Field : 代表类的成员变量
》java.lang.reflect.Constructor : 代表类的构造方法



未学反射之前,如何创建对象,并调用其中的方法、属性。


Class clazz = Person.class 对应一个Class(这是一个类)的实例,相当于Person 这个运行时类本身的.class 文件对应的类充当了 Class 的实例。clazz :栈空间引用,Person.class 堆空间实体。Person 类本身的所有的东西 对 clazz 完全公开。



一:理解反射的源头 Class 类

Class 类:是反射的源头,Java 程序编译完成后,生成的每一个.class 文件(在内存中,叫运行时类)就是一个Class 的一个实例。

Java 编译器编译好java 文件后,产生.class 文件在磁盘中,这种class 文件是二进制文件,内容是只有JVM虚拟机能是别的机器码,JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class 对象。


注意:

1.每一个运行时类只加载一次。

2.可以获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解...)

3.调用对应的运行时类的指定的结构(属性、方法、构造器)

4.反射的应用:动态代理。



二:如何获取Class 的实例(4种)

1.调用运行时类本身的.class


2.通过运行时类的对象获取


3.通过Class 的静态方法获取。Class.forName(className),其中的className 也就是要获取的类的类路径(注意此时会有异常,因为类有可能不在)


4.通过类的加载器






三、有了Class 实例后,便可以创建运行时类的对象:

调用Class 的newInstance()方法,创建运行时类的对象。

要求:1)类必须要有一个无参的构造器。

2)类的构造器的访问权限足够(能被使用)。



四、通过反射调用类得完整结构

(一)获取属性

1)getField(String)获取运行时类中声明为public 的指定属性名为***的属性。

2)getDeclaredField(String) 获取运行时类中指定的名为...的属性

属性名.setAccessible(true) :由于属性权限符的限制,为了保证可以给属性赋值,需要在操作前使此属性可被操作

若要调用非静态属性,需要有对应的对象。

3)getFields()方法,获取 运行时类及其父类中的 对应的 所有的public属性,返回值类型Field[] 数组形式。

4)getDeclaredFields()方法,能获取到 运行时类本身的所有属性,无关访问权限。



5) 获取属性的各个部分的内容。
①获取每个属性的权限修饰符
格式:获取到的属性.getModifiers();返回值类型为int {1:public 2:private 0:缺省,4: protected, 若想不显示数字,而显示public等,就要翻译过来,调用 Modifier.toString(int),返回值类型为String}
②获取属性的变量类型
格式:获取到的属性.getType();返回值类型 Class
③获取属性名
格式:获取到的属性.getName();返回值类型 String



(二)获取方法

1)非静态方法

①公有的(public)

1.需要指定方法名,方法参数类型(String.class)

Method m = clazz,getMethod("show");方法名 为 show,形参没有。

2.调用该指定的方法:m.invoke(对象,参数列表),形参若没有,就不用写

②私有的(缺省,protected,private)

1.getDeclaredMethod(.....);

2.Method对象.setAccessible(true);设置对方法允许访问

3.调用方法:Method对象.invoke(.......);


2)静态方法,不需要创建对象

①需要指定方法名

②调用该指定的方法:m.invoke(对象,参数列表),如:m.invoke(Person.class)



(三)调用构造器

1.Class 类实例.getDeclaredConstructor(参数实例);返回值类型Constructor。

Class类的实例.getDeclaredConstructors(); 返回值Constructor[] 数组。


2.必要时加上 Constructor 对象.setaccessible(true);
3.Constructor 对象.newInstance(...);来创建运行时类对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值