Java反射机制

 

什么是反射

 

    java的反射机制可以说也是java比较核心的部分,及通过字节码文件来创建对象,访问其成员变量和调用其成员方法。且这种访问无论该对象是否私有都能被访问到,也被称作暴力访问。这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。当类被编译后,JVM将对其生成.class文件,也就是字节码文件,该文件包含了所对应类的信息,当然是以二进制的方法进行存储的,由JVM分析,识别,和执行。

 


反射获取字节码对象

(1)创建一个类用于测试

    使其构造方法,成员变量,方法都为私有的

public class Cat{
    private Cat(String name){
        this.name = name;
    }
    private int age;
    private String name;
    private void printName(String frame){
        System.out.println(frame+":"+name);
    }
}

(2)获取Class(字节码)对象的三种方法

public class Reflect {
    public static void main(String[] args){
        //通过类的对象获取字节码对象
        Cat cat = new Cat();
        Class class1 = cat.getClass();
        //通过类的.class获取字节码对象
        Class class2 = Cat.class;
        //通过名字查找字节码对象(名字为该类的全路径)
        Class class3;
        {
            try {
                class3 = Class.forName("com.company.Cat");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

 

类与class类对应的对象

 

    class类是java中一个较为特殊的类,其包含了描述变量的Field,描述方法的Method,描述构造方法的Constructor,class类只能由系统创建,且每个java类都对应了一个class对象,有且仅有一个(及一个类在JVM中只对应一个class对象)。

    reflec反射API中的四个核心类:

Class类:反射的核心类,可以获取构造方法,方法,成员变量等,可暴力访问任何类。
Field类:Java.lang.reflec包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。 
Method类: Java.lang.reflec包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。 
Constructor类: Java.lang.reflec包中的类,表示类的构造方法。

 

反射的应用

    字节码对象拥有两个方法getDeclaredConstructor()和getConstructor(),getConstructor()是不可以访问除public以外的其他对象的,getDeclaredConstructor()则可以暴力访问,但是需要调用setAccessible()方法设置其值为ture,才能暴力访问。

(1)使用反射获取对象

public class Reflect {
    public static void main(String[] args){
        Class CatClass = Cat.class;
        try {
            Constructor constructor = CatClass.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);//暴力访问
            Cat cat = (Cat) constructor.newInstance("小白");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

(2)使用反射获取成员变量并修改其值

public class Reflect {
    public static void main(String[] args){
        Class CatClass = Cat.class;
        try {
            //如果该类的对象的构造方法不是私有的也可以直接new出对象来
            Constructor constructor = CatClass.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);//暴力访问
            Cat cat = (Cat) constructor.newInstance("小白");
            Field[] fs = CatClass.getDeclaredFields();
            for(Field f:fs){
                System.out.println(f);
            }
            //获取成员变量,传入成员变量的值
            Field field = CatClass.getDeclaredField("name");
            //给成员变量赋值
            field.setAccessible(true);//暴力访问
             //第一个参数表示该成员所属与哪个类,第二个参数为设置的值
            field.set(cat,"小黑");
            //读取Field值
            System.out.println(field.get(cat));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

(3)使用反射获取成员方法并调用

public class Reflect {
    public static void main(String[] args){
        Class CatClass = Cat.class;
        try {
            //如果该类的对象的构造方法不是私有的也可以直接new出对象来
            Constructor constructor = CatClass.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);//暴力访问
            Cat cat = (Cat) constructor.newInstance("小白");
            //获取方法 第一个参数为方法名,其后的参数为调用方法所需要传入的参数
            Method method = CatClass.getDeclaredMethod("printName",String.class);
            method.setAccessible(true);
            method.invoke(cat,"暴力访问");
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

 

Class类所包含的重要方法

class类中很多方法对应了一个Declared方法,其无论获取对象是否私有均可访问

获取内容方法签名
获取构造器

Constructor<T> getConstructor(Class<?>... parameterTypes)

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

包含的方法

Method getMethod(String name, Class<?>... parameterTypes

Method getDeclaredMethod(String name, Class<?>... parameterTypes))

获取成员变量

Field getField(String name

Field getDeclaredField(String name))

包含的Annotation<A extends Annotation> A getAnnotation(Class<A> annotationClass)
内部类Class<?>[] getDeclaredClasses()
外部类Class<?> getDeclaringClass()
所实现的接口Class<?>[] getInterfaces()
修饰符int getModifiers()
获取所在包Package getPackage()
获取类名String getName()

获取简称

String getSimpleName()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值