反射及动态代理

反射(Reflect)

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。

  1. 在运行时构造任意一个类的对象。
  2. 运行时获取任意一个类所具有的成员变量和方法。
  3. 在运行时调用任意一个对象的方法(属性)。
    Java 是一门面向对象的语言。在面向对象的世界里,万事万物皆对象,既然万事万物皆对象。我们写的每一个类都可以看成一个对象,是 java.lang.Class 类的对象。当我们写完一个类的Java文件,编译成class文件的时候,编译器都会将这个类的对应的class对象放在class文件的末尾。保存了类的元数据信息,一个类的元数据信息包括属性,方法,构造器,实现了哪些接口等等,这些信息在Java里都有对应的类来表示。

Class类

Class是一个类,封装了当前对象所对应的类的信息。
Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等。
对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。对象只能由系统建立对象,一个类(而不是一个对象)在 JVM 中只会有一个Class实例。
获取Class对象的三种方式

  1. 通过类名获取 类名.class
  2. 通过对象获取 对象名.getClass()
  3. 通过全类名获取 Class.forName(全类名)

Class类的常用方法

方法名功能说明
static Class forNmae(String name)返回指定类名的Class对象
Object newInstance()调用缺省构造函数,返回该Class对象的一个实例
Object newInstantce(Object []args)调用当前格式构造函数,返回Class对象的一个实例
getName()返回Class对象锁表示的实体(类,接口,数组类,基本类型或者void)名称
Class getSuperClass()返回当前Class对象的父类Class对象
Class [] getInterfases()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器

类加载器、构造器、Method、Field

ClassLoader

public static void testClassLoader() throws ClassNotFoundException,
        FileNotFoundException {
    //1. 获取一个系统的类加载器(可以获取)
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
    System.out.println(classLoader);


    //2. 获取系统类加载器的父类加载器(扩展类加载器,可以获取).
    classLoader = classLoader.getParent();
    System.out.println(classLoader);


    //3. 获取扩展类加载器的父类加载器(引导类加载器,不可获取).
    classLoader = classLoader.getParent();
    System.out.println(classLoader);


    //4. 测试当前类由哪个类加载器进行加载(系统类加载器):
    classLoader = Class.forName("xx.xx.xxxx")
            .getClassLoader();
    System.out.println(classLoader);


    //5. 测试 JDK 提供的 Object 类由哪个类加载器负责加载(引导类)
    classLoader = Class.forName("java.lang.Object")
            .getClassLoader();
    System.out.println(classLoader);
}

Constructor

 /*构造器相关*/
    public void testConstructor() throws Exception{
        String className = "xx.xx.xxxx.Person";
        Class<Person> clazz = (Class<Person>) Class.forName(className);

        System.out.println("获取全部Constructor对象-----");
        Constructor<Person>[] constructors
                = (Constructor<Person>[]) clazz.getConstructors();
        for(Constructor<Person> constructor: constructors){
            System.out.println(constructor);
        }


        System.out.println("获取某一个Constructor 对象,需要参数列表----");
        Constructor<Person> constructor
                = clazz.getConstructor(String.class, int.class);
        System.out.println(constructor);

        //2. 调用构造器的 newInstance() 方法创建对象
        System.out.println("调用构造器的 newInstance() 方法创建对象-----");
        Person obj = constructor.newInstance("Mark", 18);
        System.out.println(obj.getName());
    }

Field

/*域相关*/
    public void testField() throws Exception{
        String className = "xx.xx.xxxx.Person";
        Class clazz = Class.forName(className);

        System.out.println("获取公用和私有的所有字段,但不能获取父类字段");
        Field[] fields = clazz.getDeclaredFields();
        for(Field field: fields){
            System.out.print(" "+ field.getName());
        }
        System.out.println();
        System.out.println("---------------------------");


        System.out.println("获取指定字段");
        Field field = clazz.getDeclaredField("name");
        System.out.println(field.getName());

        Person person = new Person("ABC",12);
        System.out.println("获取指定字段的值");
        Object val = field.get(person);
        System.out.println(field.getName()+"="+val);

        System.out.println("设置指定对象指定字段的值");
        field.set(person,"DEF");
        System.out.println(field.getName()+"="+person.getName());

        System.out.println("字段是私有的,不管是读值还是写值," +
                "都必须先调用setAccessible(true)方法");
        field = clazz.getDeclaredField("age");
        field.setAccessible(true);
        System.out.println(field.get(person));
    }

Method

 /*方法相关*/
    public void testMethod() throws Exception{
        Class clazz = Class.forName("xx.xx.xxxx.Person");

        System.out.println("获取clazz对应类中的所有方法," +
                "不能获取private方法,且获取从父类继承来的所有方法");
        Method[] methods = clazz.getMethods();
        for(Method method:methods){
            System.out.print(" "+method.getName()+"()");
        }
        System.out.println("");
        System.out.println("---------------------------");

        System.out.println("获取所有方法,包括私有方法," +
                "所有声明的方法,都可以获取到,且只获取当前类的方法");
        methods = clazz.getDeclaredMethods();
        for(Method method:methods){
            System.out.print(" "+method.getName()+"()");
        }
        System.out.println("");
        System.out.println("---------------------------");

        System.out.println("获取指定的方法," +
                "需要参数名称和参数列表,无参则不需要写");
        //  方法public void setName(String name) {  }
        Method method = clazz.getDeclaredMethod("setName", String.class);
        System.out.println(method);
        System.out.println("---");

        //  方法public void setAge(int age) {  }
        /* 这样写是获取不到的,如果方法的参数类型是int型
        如果方法用于反射,那么要么int类型写成Integer: public void setAge(Integer age) {  }
        要么获取方法的参数写成int.class*/
        method = clazz.getDeclaredMethod("setAge", int.class);
        System.out.println(method);
        System.out.println("---------------------------");


        System.out.println("执行方法,第一个参数表示执行哪个对象的方法" +
                ",剩下的参数是执行方法时需要传入的参数");
        Object obje = clazz.newInstance();
        method.invoke(obje,18);

        /*私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true);*/
        method = clazz.getDeclaredMethod("privateMethod");
        System.out.println(method);
        System.out.println("---------------------------");
        System.out.println("执行私有方法");
        method.setAccessible(true);
        method.invoke(obje);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值