Java反射 | 基础篇

253 阅读4分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

JAVA反射

概念

在 Java 中的反射是指在程序运行状态中,对于任意一个类都能够知道这个类所有的属性和方法(不管是这个类的私有方法还是私有属性、或者是这个类实现的接口、继承的类,都可以通过反射来获取到);并且对于任意一个对象,都能够调用它的任意一个方法。通过反射把Java类中的成员变量、方法等信息映射成一个个的Java对象,例如把Java类中的成员变量映射为Field类、方法映射为Method类、构造方法映射为Constructor类。这种动态获取信息以及动态调用对象方法的功能就是Java的反射机制。

为什么需要反射

在 Java 程序中许多对象在运行时都会出现两种类型:编译时类型和运行时类型。 编译时的类型由声明对象时使用的类型来决定,运行时的类型由运行时实际赋值给对象的类型决定。如:List<String> p=new ArrayList<>();其中编译时类型为 List,运行时类型为 ArrayList。编译时类型是无法获取具体方法的。比如,程序在运行时可能接收到外部传入的对象,如该对象的编译时类型为 Object,但是程序却需要调用该对象的运行时类型的方法,然而,编译时根本无法预知该对象属于哪些类,也就无法知道该对象有哪些方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息,此时就必须使用到反射,在运行时来获取对象和类的相关信息。

反射使用步骤

  1. 获取想要操作的类的Class对象,通过 Class 对象我们可以调用类的任意方法及属性。

  2. 调用 Class 类中提供的方法,即反射的使用阶段。

  3. 使用反射 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:

  1. 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

  1. Field 类:Java.lang.reflec 包中的类,描述一个类中属性,包含属性的名字、数据类型、访问修饰符等,可以用来获取和设置类中的属性值。
  • set(Object obj, Object value) 将指定对象参数上的此Field对象表示的字段设置为指定的新值.
  1. Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息(包括返回值类型、方法参数等)或者执行方法(通过Method对象的invoke()方法就可以调用类中的方法)。
  • Class<?>[] getParameterTypes() 获取方法的所有参数类型
  • public Class<?> getReturnType() 获取方法的返回值类型
  1. 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反射的简单介绍,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍

默认标题_动态分割线_2021-07-15-0.gif