Java反射(一)

来源:互联网 发布:知否之风的下一句 编辑:程序博客网 时间:2024/06/15 21:58

1.

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

2.

反射大大的提高了程序的扩展性。反射是程序为外部提供了接口和配置文件,通过对接口的实现和对配置文件的配置,程序通过反射会自动加载实现了接口的类,从而读取类中内容,实现程序的扩展。

3.

通过一个类的字节码文件获得该类的属性和方法。通过class文件对象去使用该文件中的成员变量,构造方法,成员对象要想这样使用,必须先得到class文件的对象,其实就是的到class类的对象    class类包括:        成员变量        构造方法        成员方法获取class文件对象的方式    A:object类的getClass()        --Person p = new Person();          Class c = p.getClass();    B: 数据类型的静态属性class        --Class c = Person.class;或        --Class c = int.class;或        --Class c = String.class;    C: class类中的静态方法    --public static Class forName(String className)    --括号内的部分写的是类的带包全路径,即使是在同一个包下也要写全路径,否则会报找不到异常    --Class c = Class.forName("com.qfxa.Person");

一般我们使用哪一种呢?
A:自己玩 可以任选一种,第二种比较方便
B: 开发 选第三种
因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。

4.通过反射获取构造方法并使用

通过反射获取构造方法并使用1)获取字节码文件对象    Class c = Class.forName("com.qfxa.Person");2)获取构造方法            public Constructor[] getConstructors(); --所有public的构造方法            --返回一个包含某些Constructor对象的数组,这些对象反映此Class对象所表示的类的所有**公共**构造方法。            Constructor[] cons = c.getConstructors();            //遍历获取的构造方法            for(Constructor con : cons){                System.out.println(con);            }2)想获取所有的构造方法,可以用        public Constructor[] getDeclaredConstructors();         这个方法,返回Constructor对象的一个数组,这些对象反映此Class对象表示的类声明的**所有**构造方法。        --Constructor[] cons = c.getDeclaredConstructors();  想获取单个构造方法,可以用(但是只能获得public修饰的构造方法)        public Constructor getConstructor(Class<?>...parameterTypes)        --...代表可变参数,有参数也行没有参数也行        --因为构造方法的参数可能有很多个也可能没有,所以用可变参数来代替所有的参数。        --参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象。        --Constructor con = c.getConstructor(); //返回的是空参构造方法对象。        --Constructor con = c.getConstructor(String.class,int.class,String.class);//返回的是例子中的三参构造方法对象。    通过反射获取私有的构造方法        public Constructor getDeclaredConstructor(Class<?>...parameterTypes)        --Constructor con = c.getDeclaredConstructor(String.class);         --这样会获得私有的构造方法,但是不能访问,因为私有的构造方法在外界不能访问。        --con.setAccessible(true);  --通过这样设置,值为true代表反射的对象在使用时应取消java语言访问检查,这时候就可以访问私有构造方法了。3)根据获取的构造方法创建新实例        --用的方法:public T newInstance(Object... initargs)        --使用此Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。        --T代表泛型        --Object obj = con.newInstance();   --obj表示的是Person类的对象        --Object obj = con.newInstance("tom",12,"haha");        --表示是通过三参构造方法获得的新实例。

5.通过反射获取成员变量并使用

通过反射获取成员变量并使用    --获取所有成员    getFields.getDeclaredFields    --获取单个成员    getFields.getDeclaredField    --修改成员的值    set(Object obj,Object value)    //将指定对象上此Field对象表示的字段设置成指定的新值。
import java.lang.reflect.Constructor;import java.lang.reflect.Field;//通过反射获取成员变量并使用public class ReflectDmeo {    public static void main(String[] args) throws Exception {        //获取字节码文件对象        Class c = Class.forName("com.qfxa.Person");        //获取所有的public成员变量        Field[] fields1 = c.getFields();        for(Field field : fields1){            System.out.println(field);        }        //获取所有的成员变量        Field[] fields =  c.getDeclaredFields();        for(Field f : fields){            System.out.println(f);        }        //获取单个成员变量        //获取address并对其赋值        /**         * Person p = new Person();         * p.address = "Beijing";         * System.out.println(p);         */        Field addressField = c.getField("address");        //通过无参构造创建对象        Constructor constructor = c.getConstructor();        Object object = constructor.newInstance();        //System.out.println(object);        //public void set(Object obj,Object value)        //将指定对象变量上此Field对象表示的字段设置为指定的新值。        addressField.set(object, "beijing");    //给object对象的addressField字段设置值为北京        /**         * 需求:通过反射获取成员变量并使用         * 1.获取类的字节码文件对象         *      --Class c = Class.forName("com.qfxa.Person");         * 2.获取单个成员变量address         *      --Field addressField = c.getField("address");         * 3.通过无参构造创建对象(原因是给成员变量设置新值时需要指定是哪个对象,所以需要创建一个对象)         *      --Constructor constructor = c.getConstructor();         *      --Object object = constructor.newInstance();         * 4.将指定对象变量上此Field对象表示的字段设置为指定的新值         *      --addressField.set(object, "beijing");          */        //获取成员变量name并对其赋值        //Field nameField = c.getField("name"); --会报下面错误        //Exception in thread "main" java.lang.NoSuchFieldException: name        //报错是因为name这个成员变量是私有的,所以要用另一个方法getDeclaredField        Field nameField = c.getDeclaredField("name");        //Exception in thread "main" java.lang.IllegalAccessException: Class com.qfxa03.ReflectDmeo can not access a member of class com.qfxa.Person with modifiers "private"        //还报错是因为获取的成员变量name是私有的,不能访问,所以要设置setAccessible为true        nameField.setAccessible(true);        //修改成员变量name的值        nameField.set(object, "linqingxia");        System.out.println(object);        //获取成员变量age并赋值        //管他的,直接用getDeclaredField方法调用,以便于能获得私有的成员变量        Field ageField = c.getDeclaredField("age");        //同样,管他的,直接设置了取消java的访问检查,以便于能对私有成员变量进行访问        ageField.setAccessible(true);        //设置新建的object对象的age为指定值        ageField.set(object, 10);        System.out.println(object);    }}

6.通过反射获取成员方法并使用

获取所有方法    --getMethods    --getDeclaredMethods获取单个方法    --getMethod    --getDeclaredMethod暴力访问    --method.setAccessible(true);
package com.qfxa04;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class ReflectDemo {    public static void main(String[] args) throws Exception{        //获取字节码文件        Class c = Class.forName("com.qfxa.Person");        //获取所有的方法            --Method[] methods = c.getMethods();    //--获取自己的和父亲的public方法            --Method[] methods = c.getDeclaredMethods();    //--获取自己的所有方法不包括父亲的        //获取单个方法并使用            /**             * Person p = new Person();             * p.show();             */        //获得构造方法        Constructor con = c.getConstructor();        //根据构造方法创建对象        Object object = con.newInstance();        //要拿到public void show()方法        //获取单个方法需要用到这个方法            --public Method getMethod(String name,Class<?>...ParameterTypes)            --第一个参数表示的参数名,第二个参数表示的是方法的参数的class类型        Method m1 = c.getMethod("show");        //public Object invoke(Object obj,Object... args)        --返回的是object接收,第一个参数表示对象是谁,第二个参数表示调用该方法的参数        m1.invoke(object);  //其本质是调用objec的m1方法        --因为show 方法没有返回值也没有参数,所以这样写。        //获得public void method(String s)这个方法        Method m2 = c.getMethod("method", String.class);        m2.invoke(object, "hahaha");        //获取public String getString(String s,int i)这个方法        Method m3 = c.getMethod("getString", String.class, int.class);        Object objString = m3.invoke(object, "haha", 10);或者        String string = (String)m3.invoke(object, "hahah", 10);         --当你知道返回的具体是什么类型的时候可以直接强制转成对应类型,否则用object接收,因为object可以接收所有类型        System.out.println(objString);        System.out.println(string);        //获得private void function()这个方法        Method m4 = c.getDeclaredMethod("function");        m4.setAccessible(true);        m4.invoke(object);    }}
原创粉丝点击