Java反射

为了解决在运行期,对某个实例一无所知的情况下,如何调用其信息。
Java的反射是指程序在运行期间可以拿到一个对象的所有信息

1.Class类

a.除了基本数据类型外,其他类型都是class(包括interface),class的本质也是数据类型(Type)。
b.class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载到内存。
c.JVM每次动态加载时,会创建一个Class类型的实例,并在实例中保存所有的class信息,包括包名、类名、字段、方法等,因此获取了某个Class实例就可以通过这个Class实例获取到该实例对应的class的所有信息。
d.Class实例是JVM内部创建的,因为Class类的构造方法是private,只有JVM能创建,我们的java程序无法创建。

e.通过Class实例获取class信息的方法称为反射。
f.获取class的Class实例
        i.通过class的静态变量class。
                1.Class cls = String.class;
        ii.通过实例提供的getClass()方法。
                1.Class cls = "Hello".getClass();
        iii.通过静态方法 Class.forName()方法,里面写class的完整类名。
                1. Class cls = Class.forName("java.lang.String");
g.因为Class实例在JVM中是唯一的。获取到同一个实例可以用==比较。通常情况下,应该用instanceof判断数据类型,因为instanceof不但匹配指定类型,还匹配指定类型的子类;==可以精确的判断数据类型,但不能做子类比较。

h.动态加载:JVM在执行java程序时,并不是一次性把所有用到的类都加载到内存,第一次需要用到时才加载。

2.访问字段

a.通过Class实例的方法可以获取Field实例。
b.通过Class实例获取字段Field实例的方法。
        i.getField(name):根据字段名获取某个public的字段名(包括父类)
        ii.getDeclaredField(name):根据字段名获取当前类的某个field包括private(不包括父类)
        iii.getFields():获取所有public的field(包括父类)
        iv.getDeclaredFields():获取当前类的所有field包括private(不包括父类)

c.Java的反射API提供的Field实例包含了字段的所有信息。
        i.getModifiers():字段修饰符:private、public
        ii.getType():字段类型:String、int
        iii.getName():字段名称:name、score
d.通过反射读写字段是一种非常规用法,它会破坏对象的封装性。
e.获取字段值,get(Object obj)方法。
        i.通过反射拿到Field实例,还可以进一步拿到Field实例对应的该字段的值。
f.设置字段值,set(Object obj)方法。
       i.通过反射拿到Field实例,可以直接修改字段的值。

3.调用方法

a.Method实例
        i.通过Class实例的方法可以获取Method实例。
        ii.通过Class实例获取方法Method实例的方式。
                1.getMethod(name, Class...):获取某个public的Method(包括父类)
                2.getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
                3.getMethods():获取所有public的Method(包括父类)
                4.getDeclaredMethods():获取当前类的所有Method(不包括父类)

        iii.Java的反射API提供的Method实例封装了方法的所有信息。
                1.getModifiers():方法的修饰符:public、private
                2.getReturnType():方法的返回值类型:int、string.class
                3.getName():方法名称:getName()
                4.getParameterTypes():方法的参数类型:int、string.class
b.调用方法
        i.获取到Method实例后,就可以调用对应实例的对应方法。
        ii.获取到方法后调用方法,使用invoke调用,第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要和方法参数一致。

c.调用静态方法
        静态方法调用,无需指定实例对象,invoke方法的第一个参数永远为null。

d.通过反射调用方法时,仍然遵循多态原则:总是调用实际类型的重写方法。

4.调用构造方法

a.Java的反射API提供的Constructor实例封装了构造方法的所有信息,可以创建一个实例。
b.可以调用Class.newInstance()创建实例,java9已废弃,只能调用该类的public无参构造方法。
c.通过Class实例获取构造方法Constructor实例的方式。
        i.getConstructor(Class...):获取某个public的Constructor;
        ii.getDeclaredConstructor(Class...):获取某个Constructor,包括private;
        iii.getConstructors():获取所有public的Constructor;
        iv.getDeclaredConstructors():获取所有Constructor,包括private。
        注意:Constructor总是当前类的构造方法,和父类无关,不存在多态问题。

5.获取继承关系

a.获取父类的class
        i.getSuperclass()
        ii.除Object外,其他任何非Interface的Class都必定存在一个父类类型。

b.获取interface
        i.由于一个类可能实现多个接口,通过Class实例可以获取实现的接口类型,getInterfaces()。
        ii.getInterfaces()只返回当前类直接实现的接口类型,不包括父类实现的接口类型。
        iii.对所有interface的Class调用getSuperClass返回都是null。
        iv.如果一个类没有实现任何接口,调用getInterfaces()返回空数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值