1.前言
最近接触到了Java中一个很重要的概念,因此记录下学习过程,给大家些参考,也方便我以后的复习。
2.反射的概念
反射是 Java 的一种特性,可以让程序在运行时获取自身的信息,并且动态地操作类或对象的属性、方法和构造器等。通过反射功能,可以让我们在不知道具体类名的情况下,依然能够实例化对象,调用方法以及设置属性。以我的话来解释反射的话就是当你需要一个对象,但是不知道什么类型时;还想调用对象的属性,为属性赋值;需要调用对象的方法,并且执行该方法时就可以使用反射。
3.反射的用法——获取字节码信息
首先要获取字节码文件,这是使用反射的基础。获取字节码的方法有4种。
1.调用Class类提供的静态方法forName
Class c1 = Class.forName("");
方法里传的是一串字符串,是类所在的全限定名,比如"com.daxue.test02.Person"
这是在四种方法中最常用的一种。
2.利用类的加载器
ClassLoader loader = Test.class.getClassLoader();
Class c2 = loader.loadClass("com.daxue.test02.Person");
Test是测试类的对象,按照自己的项目名称调整。getClassLoader()是类的一个方法,功能是获取当前类的加载器。
3.通过getClass()方法获取
Person p = new Person();
Class c3 = p.getClass();
4.通过内置class属性
Class c4 = Person.class;
要注意的是,方法3和4并不常用,主要用的是1和2。
4.反射的用法——获取构造器
获取了字节码文件后就可以获取到对象的构造器了。
1.获取被public修饰的构造器。
Constructor[] c1 = cls.getConstructors();
方法以s结尾说明是获取所有的public构造器,要用数组保存,下面这个方法是获取指定的public构造器。
Constructor con1 = cls.getConstructor();
指定构造器的话要根据构造器里的参数个数确定,在上面的例子中是没有给方法传入参数,因此指定的是无参的public构造器。
Constructor con2 = cls.getConstructor(double.class, double.class);
在这里传入了两个参数,那么指定的就是有两个参的public构造器。(!!注意类中要有这个构造函数才可以)
上面介绍的都是获取public构造器的方法,那么该如何获取被privat修饰的构造器呢,不用担心,和public一样,为private同样也准备了两种方法。
Constructor[] c2 = cls.getDeclaredConstructors();
获取全部修饰符的构造器
Constructor con3 = cls.getDeclaredConstructor(int.class);
获取指定的private修饰的构造器
大家要注意区分获取public和privat方法的不同,获取private修饰元素的方法多了Declared一词。在这里提一句在反射中要获取privat修饰元素的方法和public相比都多了Declared,大家要注意这点。
3.反射的用法——创建对象
Object o1 = con1.newInstance();
System.out.println(o1);
通过Constructor对象,创建了反射类的实例。newInstance方法是Constructor类的一个方法,用于创建并返回由该构造器所表示的类的一个新实例。
Object o2 = con2.newInstance(180.5, 170.6);
System.out.println(o2);
也可以在创建实例时,就直接赋值。但要注意你获取到了什么构造器你就要用什么样的方式创建实例,比如o2就通过con2创建,con2在之前获取到了两个参数的构造器因此才可以这么创建。
4.反射的用法——获取属性
获得了实例对象后就可以对该实例的属性做操作了,可以查看,赋值等。
Field[] fields = cls.getFields();
获取被public修饰的属性,但一般情况下属性都被设为privat因此该方法不常用。
Field[] declaredFields = cls.getDeclaredFields();
获取类中的所有属性,包括private修饰的
Field score = cls.getField("score");
获取指定的属性(public修饰的),就比如上面的语句,获取名为score的属性
Field sno = cls.getDeclaredField("sno");
获取名为sno的私有属性
int modifiers = sno.getModifiers();
获取访问修饰符,如static、final、
abstract、
native、public等。获取的是修饰符的整型表示。
Class clazz = sno.getType();
获取属性的数据类型,可以再用getName()方法获取到数据类型的名字
String name = sno.getName();
获取属性的名字
Field sco = cls.getField("score");
Object obj = cls.newInstance();
sco.set(obj,98);
给属性赋值,给名为score的属性赋值。要给属性设值的话,必须要有对象
5.反射的用法——获取方法
可以获得属性,那么自然也可以获得方法。
Method[] methods = cls.getMethods();
获取类中所有被public修饰的方法
Method[] declaredMethods = cls.getDeclaredMethods();
获取类中的所有方法,包括构造函数。
Method showInfo1 = cls.getMethod("showInfo");
获取类中的指定的方法(public修饰的),获取名为showInfo的方法
Method showInfo2 = cls.getMethod("showInfo", int.class, int.class);
获取名为showInfo的方法,参数列表有两个参数,需要进行匹配
Class[] parameterTypes = work.getParameterTypes();
获取参数列表
获取玩方法后就该调用该方法了,下面展示如何调用
Object o = cls.newInstance();
showInfo1.invoke(o);
调用o对象的showInfo1方法,invoke方法是Method类的一个方法,用于调用Method
对象所表示的方法。 showInfo1方法在前面已将获取了。
6.总结
对于反射这个概念,我也还处在学习状态,有许多地方没有弄懂,记录这份笔记的目的不只是方便我复习,也希望能帮到一些初学者。在我的这份笔记中还有很多内容没有记录,记录的部分也可能有错,我希望大家能积极指出我的错误,在此提前感谢大家了。