zoukankan      html  css  js  c++  java
  • java反射的用法

    反射(运行时的类信息),在java里面得到了大量的使用,尤其是在一些框架里面(注解等等),多多少少都会用到反射,了解java的反射,对我们以后学习框架和写框架都会起到非常的重要!

    Class类与java.lang.reflect类库一起对反射的概念进行了支持,该类库包括了FieId、Method以及Constructor类。这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。这样你就可以使用Constructor创建新的对象,用get()和set()方法读取和修改与FieId对象关联的字段,用invoke()方法调用与Method对象关联的方法,另外还可以调用getFieIds()、getMethods()和getConstructors()等很便利的方法,以返回表示字段、方法以及构造器的对象的数组。

    首先,我们创建一个类,代码如下

    public class ReflexObject {
        
        private int a;
        protected int b;
        int c;
        public int d;
        
        public ReflexObject(){
            super();
        }
    
        public ReflexObject(int a, int b, int c, int d) {
            super();
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
        }
        
        private void setA(int a){
            this.a=a;
            System.out.println("我是公有方法");
        }
        
        protected void setB(int b){
            this.b=b;
            System.out.println("我是私有方法");
        }
        
        void setC(int c){
            this.c=c;
            System.out.println("我是包方法");
        }
        
        public void setD(int d){
            this.d=d;
            System.out.println("我是受保护方法");
        }
    
        @Override
        public String toString() {
            return "ReflexObject [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + "]";
        }
        
    }

    1⃣️通过getConstructors()、getMethods()和getFields()方法获取类里面的信息,代码如下

    public static void main(String[] args) {
        Constructor<?>[] constructors = ReflexObject.class.getConstructors();//获取类里面的构造器方法
        Method[] methods = ReflexObject.class.getMethods();//获取类里面的方法
        Field[] fields = ReflexObject.class.getFields();//获取类里面的属性
        for(Constructor<?> c:constructors){
            System.out.println(c.toString());
        }
        System.out.println("-------------------------------");
        for(Method m:methods){
            System.out.println(m.toString());
        }
        System.out.println("-------------------------------");
        for(Field f:fields){
            System.out.println(f.toString());
        }
        System.out.println("-------------------------------");
    }

    输出结果

    可以看到,通过getConstructors()、getMethods()和getFields()方法获取类里面的信息只能是公有的,并且可以获取到父类Object的公有方法。

    2⃣️用invoke()方法调用与Method对象关联的方法,代码如下

    public static void main(String[] args) {
        ReflexObject rObj=new ReflexObject();
        System.out.println(rObj);
        try {
            Method methodA = ReflexObject.class.getDeclaredMethod("setA", int.class);
            Method methodB = ReflexObject.class.getDeclaredMethod("setB", int.class);
            Method methodC = ReflexObject.class.getDeclaredMethod("setC", int.class);
            Method methodD = ReflexObject.class.getDeclaredMethod("setD", int.class);
            methodA.setAccessible(true);
            methodA.invoke(rObj, 3);
            methodB.setAccessible(true);
            methodB.invoke(rObj, 3);
            methodC.setAccessible(true);
            methodC.invoke(rObj, 3);
            methodD.setAccessible(true);
            methodD.invoke(rObj, 3);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(rObj);
    }

    因为invoke(obj,args...)是Method方法,并不知道是要那个对象obj执行改方法,必须指定需要修改那个对象obj,传递的参数args

    输出结果如下

    可以看到,的确是把将属性0都改成了3,执行了方法,甚至是private方法。注意,除了public方法外,其它的都要将setAccessible设置为true,这个大家可以试一下。

    3⃣️通过FieId类直接修改属性值

    public static void main(String[] args) {
        ReflexObject rObj=new ReflexObject();
        System.out.println(rObj);
        try {
            Field fieldA = ReflexObject.class.getDeclaredField("a");
            Field fieldB = ReflexObject.class.getDeclaredField("b");
            Field fieldC = ReflexObject.class.getDeclaredField("c");
            Field fieldD = ReflexObject.class.getDeclaredField("d");
            fieldA.setAccessible(true);
            fieldA.set(rObj, 3);
            fieldB.setAccessible(true);
            fieldB.set(rObj, 3);
            fieldC.setAccessible(true);
            fieldC.set(rObj, 3);
            fieldD.setAccessible(true);
            fieldD.set(rObj, 3);
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(rObj);
    }

    输出结果

     

    结论和注意点类似2⃣️

    4⃣️通过Constructor反射出一个对象,代码如下

    public static void main(String[] args) {
        try {
            Constructor<ReflexObject> constructor1 = ReflexObject.class.getDeclaredConstructor();//无参数构造器
            Constructor<ReflexObject> constructor2 = ReflexObject.class.getDeclaredConstructor(int.class,int.class,int.class,int.class);//带参数的构造器
            ReflexObject object1 = constructor1.newInstance();
            ReflexObject object2 = constructor2.newInstance(3,3,3,3);
            System.out.println(object1);
            System.out.println(object2);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    输出结果如下

    这里我并没有将setAccessible设置为true,因为我的构造方法都是public,大家可以试一下其它的访问权限。

    ok,反射我就写到这里,如果写的有什么问题,大家可以在下面留言,谢谢!

  • 相关阅读:
    Ubuntu14.04LTS 下配置Tomcat Hadoop eclipse环境
    Ubuntu14.04LTS下 JAVA+HADOOP
    windows下libnet ARP
    windows下编译配置libnet-1.2-rc3
    windows下安装配置winpcap
    python--装饰器初阶
    python--函数进阶
    python_函数基础
    python_文件操作
    python_Set(集合)
  • 原文地址:https://www.cnblogs.com/pig-brother/p/7242299.html
Copyright © 2011-2022 走看看