今天我们简单的说说java中的反射
反射算是一个比较难理解的知识,但是如果你的面向对象思想很好,那么反射也不难理解
反射就是动态获取类(即字节码文件),并对其成员进行操作,包括对其属性,构造方法以及普通方法的操作
只用一个class文件(字节码文件)就可以实现和new一个对象一样的效果
其实反射就是把字节码文件面向对象了,虽然每个类的属性方法都不同,但是它们都有个共性,就是它们都有属性,构造方法,方法,其中,属性为Field类型的,构造方法是Constructor类型的,方法是Method类型的
首先我们要先获取到这个字节码文件Person.class,一共有三种获取方式
第一种:使用object提供的Class<?> getClass()方法得到字节码文件,
<span style="font-size:14px;"><span style="font-size:14px;"> Person ren1=new Person();
Class<? extends Person> claz=ren1.getClass();</span></span>
这种方式需要事先存在对象,对我们的作用并不大,我们用反射就是为了在不能创建对象时通过反射的方式实现和new对象一样的效果,所以这种方式几乎没什么作用,
接着说第二种方式:每种数据类型都有一个class属性,通过该属性得到的就是字节码文件对象
<span style="font-size:14px;"><span style="font-size:14px;"> Class<Person> claz=Person.class;</span></span>
这种方式就不需要事先存在对象了,但是这种方式需要事先存在这种数据类型
第三种方式:使用Class的静态方法forName(""),字符串由包名+类名构成
<span style="font-size:14px;"><span style="font-size:14px;"> Class<?> claz = Class.forName("cn.qianfeng.reflect.Person");</span></span>
这种方式只需要一个含有包名和类名的字符串就可以了,是常用的方式
接下来我们以Person类为例,其中定义了私有属性name和age,无参构造方法,带参构造方法,非静态无参方法show方法,非静态带参方法fun,静态带参方法ff
首先动态得到字节码文件并通过构造方法创建对象,我们先使用无参的构造方法直接使用newInstance()方法即可
<span style="font-size:14px;"><span style="font-size:14px;"> //1、得到字节码文件对象
Class<?> claz=Class.forName("cn.qianfeng.reflect.Person");
//2、创建对象---使用的是空参的构造方法创建对象
Object obj=claz.newInstance();</span></span>
下面使用带参的构造方法,要先得到带参的构造方法对象然后使用newInstance方法
<span style="font-size:14px;"><span style="font-size:14px;"> //1、得到字节码文件对象
Class<?> claz=Class.forName("cn.qianfeng.reflect.Person");
//得到带参数的构造方法对象
Constructor con=claz.getConstructor(String.class,int.class);</span></span>
<span style="font-size:14px;"><span style="font-size:14px;"> Object obj=con.newInstance("李四",23);</span></span>
创建完对象,我们就可以给对象的变量赋值了下面我们看怎样给对象的属性赋值
还是要先得到字节码文件对象
Class<?> claz = Class.forName("cn.qianfeng.reflect.Person");
然后得到属性name所属的Filed类型的对象,有两种方式
1、Field field = claz.getField("name");//的到的是public权限的属性
2、Field field = claz.getDeclaredField("name");//得到已经声明的属性包含私有属性
下面给属性赋值,name属于非静态成员变量,所以要通过对象来赋值
Object obj=claz.newInstance();
因为是私有属性,所以要先设置属性为可访问的
field.setAccessible(true);
赋值
field.set(obj, "张三");
最后我们动态获取类并调用方法
先获取字节码文件对象
Class<?> claz = Class.forName("cn.qianfeng.reflect.Person");
然后得到方法所属的Method对象,第一个参数是方法的名字,第二个参数是方法的参数类型,没有参数传递null
非静态无参的:Method method=claz.getMethod("show", null);
非静态有参的:Method m=claz.getMethod("fun", String.class);
静态有参的:Method m=claz.getMethod("ff",int.class);
执行方法时还需要对象,所以要创建对象
Object obj = claz.newInstance();
然后就可以用invoke()方法执行方法了invoke()方法传递的第一个参数是person对象,第二个参数是给方法传递的实参,没有参数传递null
非静态无参的:method.invoke(obj,null);
非静态有参的:m.invoke(obj,"haha");
静态有参的:m.invoke(null,66);//不需要对象就可以创建
反射就简单介绍这些,重点是把面向对象的思想建立好,反射也就不难理解了
<span style="font-size:14px;"></span>