博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java反射的用法
阅读量:5083 次
发布时间:2019-06-13

本文共 4927 字,大约阅读时间需要 16 分钟。

反射(运行时的类信息),在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
constructor1 = ReflexObject.class.getDeclaredConstructor();//无参数构造器 Constructor
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,反射我就写到这里,如果写的有什么问题,大家可以在下面留言,谢谢!

 

转载于:https://www.cnblogs.com/pig-brother/p/7242299.html

你可能感兴趣的文章
oracle 报错ORA-12514: TNS:listener does not currently know of service requested in connec
查看>>
python3 生成器与迭代器
查看>>
java编写提升性能的代码
查看>>
list 容器 排序函数.xml
查看>>
《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇03:暂停游戏》
查看>>
CPU,寄存器,一缓二缓.... RAM ROM 外部存储器等简介
查看>>
git .gitignore 文件不起作用
查看>>
Alan Turing的纪录片观后感
查看>>
c#自定义控件中的事件处理
查看>>
IOS--沙盒机制
查看>>
使用 JointCode.Shuttle 访问任意 AppDomain 的服务
查看>>
sqlite的坑
查看>>
digitalocean --- How To Install Apache Tomcat 8 on Ubuntu 16.04
查看>>
【题解】[P4178 Tree]
查看>>
Mongo自动备份
查看>>
cer证书签名验证
查看>>
synchronized
查看>>
【深度学习】caffe 中的一些参数介绍
查看>>
Python-Web框架的本质
查看>>
QML学习笔记之一
查看>>