java反射
1.反射机制的概念及作用(原文链接:https://blog.csdn.net/lililuni/article/details/83449088)
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
实际上,我们创建的每一个类也都是对象,即类本身是java.lang.Class类的实例对象。这个实例对象称之为类对象,也就是Class对象。那么,Class对象又是什么对象呢?
(原文链接:https://blog.csdn.net/sinat_38259539/article/details/71799078)
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
如图是类的正常加载过程:反射的原理在与class对象。
熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
其中这个Class对象很特殊。我们先了解一下这个Class类。
从图中可以得出以下几点:(原文链接:https://blog.csdn.net/lililuni/article/details/83449088)
(1)Class 类的实例对象表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有很多的实例,每个类都有唯一的Class对象。
(2)Class 类没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机自动构造的。也就是说我们不需要创建,JVM已经帮我们创建了。
(3)Class 对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
2.反射所在的包及常用的相关方法(原文链接:https://blog.csdn.net/qq_51515673/article/details/124830558)
所在包:java.lang.reflect.*;
常用的方法:
//获取包名、类名 clazz.getPackage().getName()//包名 clazz.getSimpleName()//类名 clazz.getName()//完整类名 //获取成员变量定义信息 getFields()//获取所有公开的成员变量,包括继承变量 getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量 getField(变量名) getDeclaredField(变量名) //获取构造方法定义信息 getConstructor(参数类型列表)//获取公开的构造方法 getConstructors()//获取所有的公开的构造方法 getDeclaredConstructors()//获取所有的构造方法,包括私有 getDeclaredConstructor(int.class,String.class) //获取方法定义信息 getMethods()//获取所有可见的方法,包括继承的方法 getMethod(方法名,参数类型列表) getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法 getDeclaredMethod(方法名,int.class,String.class) //反射新建实例 clazz.newInstance();//执行无参构造创建对象 clazz.newInstance(222,"韦小宝");//执行有参构造创建对象 clazz.getConstructor(int.class,String.class)//获取构造方法 //反射调用成员变量 clazz.getDeclaredField(变量名);//获取变量 clazz.setAccessible(true);//使私有成员允许访问 f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null //反射调用成员方法 Method m = Clazz.getDeclaredMethod(方法名,参数类型列表); m.setAccessible(true);//使私有方法允许被调用 m.invoke(实例,参数数据);//让指定实例来执行该方法
3.反射获取类对象的三种方式(原文链接:https://blog.csdn.net/qq_51515673/article/details/124830558)
① 调用某个类的对象的getClass()方法,即:对象.getClass();
Person p = new Person();
Class clazz = p.getClass();
注意:此处使用的是Object类中的getClass()方法,因为所有类都继承Object类,所以调用Object类中的getClass()方法来获取。
② 调用类的class属性类获取该类对应的Class对象,即:类名.class
Class clazz = Person.class;
③ 使用Class类中的forName()静态方法(最安全,性能最好)即:Class.forName(“类的全路径”)
Class clazz = Class.forName("类的全路径");
注意:在运行期间,一个类,只有一个Class对象产生。
三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。
package com.reflection; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.Arrays; public class Person { private String name; public int age; public Person() {} public Person(String n,int a) { name = n; age = a; } public void run() { System.out.println("跑"); } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Person p = new Person(); //1.调用某个类的对象的getClass()方法,即:对象.getClass(); Class class1 = p.getClass(); Object Field[] = class1.getDeclaredFields(); for(int i=0;i<Field.length;i++) { System.out.println(Field[i]); } //2.调用类的class属性类获取该类对应的Class对象,即:类名.class Class class2 = Person.class; Object Constructor[] = class2.getConstructors(); for(int i=0;i<Constructor.length;i++) { System.out.println(Constructor[i]); } //3.使用Class类中的forName()静态方法(最安全,性能最好)即:Class.forName(“类的全路径”) Class class3 = Class.forName("com.reflection.Person"); Method ms[] = class3.getMethods(); for(Method t:ms) { System.out.println(t); System.out.println(t.getName()); Class<?>[] pt=t.getParameterTypes(); System.out.println(Arrays.toString(pt)); } } }
参考文章:
https://blog.csdn.net/qq_51515673/article/details/124830558
https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html
https://blog.csdn.net/lililuni/article/details/83449088
https://www.cnblogs.com/adamjwh/p/9683705.html
https://blog.csdn.net/sinat_38259539/article/details/71799078