Java反射机制的简单学习

时间:2023-03-08 16:15:21
Java反射机制的简单学习

今天看了一下Java的反射机制,就此记录一下。

首先,我们要先了解一下什么是反射?

  •   反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
  •   JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

Java反射的应用

  •   Spring框架 
  •   Hibernate框架:关联映射等
  •   白盒测试   

Java反射相关API

  java.lang包下

    -Class<T>:表示一个正在运行的 Java 应用程序中的类和接口,是Reflection的起源

  java.lang.reflect包下

    -Field 类:代表类的成员变量(也称类的属性)

    -Method 类 : 代表类的方法

    -Array 类 : 提供了动态创建数组,以及访问数组的元素的静态方法

反射的类类型:Class

假设我们有一个Role类

 package _Venom_.reflection;

 public class Role {

     private String name;
private String type; //Constructors
public Role(){
System.out.println("Constructor Role() is invoking!");
} private Role(String _name){
this.name = _name;
System.out.println("Constructor Role(String _name) is invoking!");
} //get and set method
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getType() {
return type;
} public void setType(String type) {
this.type = type;
} //override the toString method to show the class
@Override
public String toString() {
// TODO Auto-generated method stub
return "This is a role called " + this.name;
} }

我们可以通过以下方式得到类类型。

获取方式

说明

示例

object.getClass()

每个对象都有此方法

获取指定实例对象的Class

List list = new ArrayList();

Class listClass = list.getClass();

class. getSuperclass()

获取当前Class的继承类Class

List list = new ArrayList();

Class listClass = list.getClass();

Class superClass = listClass. getSuperclass();

Object.class

.class直接获取

Class listClass = ArrayList.class;

Class.forName(类名)

用Class的静态方法,传入类的全称即可

try {

Class c = Class.forName("java.util.ArrayList");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Primitive.TYPE

基本数据类型的封装类获取Class的方式

Class longClass = Long.TYPE;

Class integerClass = Integer.TYPE;

Class voidClass = Void.TYPE;

Class class1 = Role.class;
try {
Class class2 = Class.forName("_Venom_.reflection.Role");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

通过类类型的newInstance方法来创建一个实例。如下

Object obj = class1.newInstance();

但是,我们通常的做法是通过Constructor类来获取类的构造方法,然后再通过Constructor类的newInstance方法来创建实例。

获取类的构造器

Constructor类:

  •   public Constructor<?>[] getConstructor()   返回类中的所有public构造器集合,默认构造器的下标为0
  •   public Constructor<T> getConstructor(Class<?>...parameterTypes) 返回指定的public构造器,参数为构造器参数类型集合
  • public  Constructor<?>[] getDeclaredConstructor() 返回类中所有的构造器,包括私有
  • public Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes) 返回任意指定的构造器
Class class1 = Role.class;
try {
Class class2 = Class.forName("_Venom_.reflection.Role");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} /**
* 获取构造方法Constructor
* getConstructor() only for public
* getDeclaredConstructor() global access all
* */
Constructor constructor = null;
//指定参数列表获取特定的方法
try {
       //1
constructor = class1.getDeclaredConstructor(new Class[]{String.class});
//设置可访问的权限 不设置会报IllegalAccessException异常
constructor.setAccessible(true); } catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} Object obj = null;
try {
obj = constructor.newInstance(new Object[]{"Venom"});
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//打印对象的信息
System.out.println(obj); //2获取所有的构造方法的集合
Constructor constructorArr[] = null;
constructorArr = class1.getDeclaredConstructors();
constructorArr[1].setAccessible(true);
Object obj1 = null;
try {
obj1 = constructorArr[1].newInstance(new Object[]{"_Venom_"});
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(obj1);
解释一下:第一个是获得一个指定的方法,我们指定了参数是一个String类型,第二段我们获得了所有的构造方法集合,并选取了其中一个创建了新的对象。
  当我们获得私有的方法的时候,要用setAccessible设置一下可访问的权限。
以此类推:
  在获取类的成员变量的时候,我们可以使用Field类
    主要的方法非常的类似:
    • public Field getDeclaredField(String name)  获取任意指定名字的成员
    • public Field[] getDeclaredFields()             获取所有的成员变量
    • public Field getField(String name)           获取任意public成员变量
    • public Field[] getFields()                          获取所有的public成员变量

  在获取类的方法的时候,我们可以使用Method类:

    • public Method[] getMethods()    获取所有的共有方法的集合
    • public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合
    • public Method[] getDeclaredMethods()  获取所有的方法
    • public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法

总结:

  感觉今天学习的Java反射机制还是很有用出的,以此Mark一下我的学习历程。