这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
JAVA反射
概念
在 Java 中的反射是指在程序运行状态中,对于任意一个类都能够知道这个类所有的属性和方法(不管是这个类的私有方法还是私有属性、或者是这个类实现的接口、继承的类,都可以通过反射来获取到);并且对于任意一个对象,都能够调用它的任意一个方法。通过反射把Java类中的成员变量、方法等信息映射成一个个的Java对象,例如把Java类中的成员变量映射为Field类、方法映射为Method类、构造方法映射为Constructor类。这种动态获取信息以及动态调用对象方法的功能就是Java的反射机制。
为什么需要反射
在 Java 程序中许多对象在运行时都会出现两种类型:编译时类型和运行时类型
。 编译时的类型由声明对象时使用的类型来决定,运行时的类型由运行时实际赋值给对象的类型决定。如:List<String> p=new ArrayList<>();
其中编译时类型为 List,运行时类型为 ArrayList。编译时类型是无法获取具体方法的。比如,程序在运行时可能接收到外部传入的对象,如该对象的编译时类型为 Object,但是程序却需要调用该对象的运行时类型的方法,然而,编译时根本无法预知该对象属于哪些类,也就无法知道该对象有哪些方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息,此时就必须使用到反射,在运行时来获取对象和类的相关信息。
反射使用步骤
-
获取想要操作的类的Class对象,通过 Class 对象我们可以调用类的任意方法及属性。
-
调用 Class 类中提供的方法,即反射的使用阶段。
-
使用反射 API 来操作这些信息。
获取Class对象的3种方式
- 调用某个对象的
getClass()
方法,如
Programmer p=new Programmer();
Class pClass=p.getClass();
- 调用某个类的 class 属性来获取该类对应的 Class 对象
Class pClass=Programmer.class;
- 使用 Class 类中的
forName()
静态方法
Class pClass=Class.forName("类的全路径"); (最常用)
当我们获得了想要操作的类的 Class 对象后,可以通过 Class 类中的方法获取并查看该类中的方法和属性。
//获取 Person 类的 Class 对象
Class class=Class.forName("reflection.Person");
//获取 Programmer 类的所有方法信息
Method[] method=class.getDeclaredMethods();
//获取 Programmer类的所有成员属性信息
Field[] field=class.getDeclaredFields();
//获取 Programmer 类的所有构造方法信息
Constructor[] constructor=class.getDeclaredConstructors();
Java反射API
几个重要的类及其对应的API:
- Class 类:反射的核心类,由 JVM 生成的,通过它能够获悉整个类的结构,如可以获取类的属性,方法等信息。Class类的常用方法
-
String getName()
:获得类的完整名字(含包名)。如com.gjy.demo.Reflect.Programmer
-
Field[] getFields()
:获得类的public类型
的属性。 -
Field[] getDeclaredFields()
:获得类的所有属性。包括private声明的 -
Method[] getMethods()
:获得类的public类型的方法。 -
Field[] getDeclaredMethods()
:获得类的所有方法。包括private声明的 -
Method getMethod(String name, Class[] parameterTypes)
:获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。 -
Constructor[] getConstructors()
:获得类的public类型的构造方法。 -
Constructor<T> getConstructor(Class<?>... parameterTypes)
:获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。如getConstructor(String.class,String.class,Integer.class)
-
T newInstance(
):通过类Class对象创建该类的一个对象。 -
String getSimpleName()
获取不包含包名的类名 -
Class getSuperclass()
获取当前类的继承类的Class
- Field 类:Java.lang.reflec 包中的类,描述一个类中属性,包含属性的名字、数据类型、访问修饰符等,可以用来获取和设置类中的属性值。
set(Object obj, Object value)
将指定对象参数上的此Field
对象表示的字段设置为指定的新值.
- Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息(包括返回值类型、方法参数等)或者执行方法(通过Method对象的
invoke()
方法就可以调用类中的方法)。
Class<?>[] getParameterTypes()
获取方法的所有参数类型public Class<?> getReturnType()
获取方法的返回值类型
- Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。
通过反射创建对象的两种方式
-
Class 对象的
newInstance()
方法 使用 Class 对象的 newInstance()方法来创建该 Class 对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空构造器。 -
调用 Constructor 对象的 newInstance() 先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance()方法来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。
//获取 Programmer 类的 Class 对象
Class class=Class.forName("reflection.Person");
//使用newInstane 方法创建对象
Programmer p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor c=class.getDeclaredConstructor(String.class,String.class,Integer.class);
//创建对象并设置属性
Programmer p1=(Person) c.newInstance("不喝奶茶的Programmer","男",20);
🏁以上就是对Java反射的简单介绍,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍