Java 反射机制详解

反射概述

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。本质就是 操作字节码文件。

反射相关的类(简述)

  • java.lang.Class 整个类的字节码,代表整个类【一个类型】
  • java.lang.reflect.Method 字节码中的方法字节码,代表类中的方法
  • java.long.reflect.Constructor 字节码中的构造方法字节码,代表类中的构造方法
  • java.long.reflect.Field 字节码中的属性字节码,代表类中的成员变量和实例变量

获取字节码文件(★★★★★)

  • 第一种:Class clazz = Class.forName(“带包名的完整类名”);
clazz_1 = Class.forName("java.lang.String");    //clazz_1代表String.calss文件,或者说代表String类型
  • 第二种:Class clazz = 对象.getClass();
Date date = new Date();
Class clazz_5 = date.getClass();	//任何一个对象都有getClass()方法
  • 第三种:Class clazz = 任何类型.class;
Class clazz_7 = Integer.class;		//clazz_7代表Integer类型

反射机制创建对象

  • 获取字节码文件
  • 通过Class对象调用newInstance()完成对象的创建
    • 调用newInstance()方法必须保证 类有无参构造方法
	Class<?> classTeacher = Class.forName("reflectdemo_02.Teacher");
    Object o = classTeacher.newInstance();
    System.out.println(o);		// reflectdemo_02.Teacher@1b6d3586

反射相关的类(详解)

(1)java.lang.Class 类 (★★★★★)

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 枚举是一种类,注释是一种接口。Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造。

常用方法

在这里插入图片描述

(2)java.long.reflect.Field 类 (★★★)

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 反射的字段可能是一个类(静态)字段或实例字段。

常用方法
  • Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。
  • int getInt(Object obj) 获取 int 类型或另一个通过扩展转换可以转换为 int 类型的基本类型的静态或实例字段的值。
  • int getModifiers() 以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符。
  • String getName() 返回此 Field 对象表示的字段的名称。
  • Class<?> getType() 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
  • int hashCode() 返回该 Field 的哈希码。
  • void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
  • void setInt(Object obj, int i) 将字段的值设置为指定对象上的一个 int 值。
  • String toString() 返回一个描述此 Field 的字符串。
(3)java.long.reflect.Method 类 (★★★)

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

常用方法
  • int getModifiers() 以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。
  • String getName() 以 String 形式返回此 Method 对象表示的方法名称。
  • Class<?>[] getParameterTypes() 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。
  • Class<?> getReturnType() 返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。
  • int hashCode() 返回此 Method 的哈希码。
  • Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。(★★★)
  • String toString() 返回描述此 Method 的字符串。
(4)java.long.reflect.Constructor 类 (★★)

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

常用方法
  • int getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。
  • String getName() 以字符串形式返回此构造方法的名称。
  • Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。
  • TypeVariable<Constructor<T>>[] getTypeParameters() 按照声明顺序返回一组 TypeVariable 对象,这些对象表示通过此 GenericDeclaration 对象所表示的一般声明来声明的类型变量。
  • int hashCode() 返回此 Constructor 的哈希码。
  • T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。(★★★)
  • String toString() 返回描述此 Constructor 的字符串。

通过反射机制反编译

package reflectdemo_06;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ResourceBundle;

/**
 * 使用反射机制反编译类【成员属性,成员方法,构造方法】
 * @Author Nigori
 * @Create 2020/9/3
 */
public class DecompilationAllReflectTest {
    public static void main(String[] args) throws Exception {
        //获取资源文件
        ResourceBundle resource = ResourceBundle.getBundle("classinfo");
        String userClass = resource.getString("userClass");

        //获取字节码文件
        Class<?> aClass = Class.forName(userClass);

        /**
         * 反编译【字符串拼接】
         */
        //创建StringBuilder
        StringBuilder builder = new StringBuilder();

        //类结构反编译
        builder.append(Modifier.toString(aClass.getModifiers()));   //类修饰符
        builder.append(" class ");
        builder.append(aClass.getSimpleName());     //类名
        builder.append(" {\n");

        //字段反编译
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            builder.append("\t");
            builder.append(Modifier.toString(field.getModifiers()));    //字段修饰符
            builder.append(" ");
            builder.append(field.getType().getSimpleName());    //字段类型
            builder.append(" ");
            builder.append(field.getName());    //字段名
            builder.append(";\n");
        }

        builder.append("\n");

        //构造方法反编译
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();       //构造方法列表
        for (Constructor<?> constructor : declaredConstructors) {
            builder.append("\t");
            builder.append(Modifier.toString(constructor.getModifiers()));      //构造方法修饰符
            builder.append(" ");
            builder.append(aClass.getSimpleName());     //构造方法名
            builder.append("(");
            //拼接参数列表
            Class<?>[] parameterTypes = constructor.getParameterTypes();    //参数列表
            for (Class<?> parameterType : parameterTypes) {
                builder.append(parameterType.getSimpleName());      //参数类型
                builder.append(",");
            }
            if (parameterTypes.length > 0) {
                builder.deleteCharAt(builder.length() - 1);
            }
            builder.append(") {...}\n");
        }

        builder.append("\n");

        //成员方法反编译
        Method[] declaredMethods = aClass.getDeclaredMethods();     //成员方法列表
        for (Method method : declaredMethods) {
            builder.append("\t");
            builder.append(Modifier.toString(method.getModifiers()));       //方法修饰符
            builder.append(" ");
            builder.append(method.getReturnType().getSimpleName());     //方法返回值类型
            builder.append(" ");
            builder.append(method.getName());       //方法名
            builder.append("(");
            //拼接参数列表
            Class<?>[] parameterTypes = method.getParameterTypes();     //方法参数列表
            for (Class<?> type : parameterTypes) {
                builder.append(type.getSimpleName());       //方法参数类型
                builder.append(",");
            }
            if (parameterTypes.length > 0) {
                builder.deleteCharAt(builder.length() - 1);
            }
            builder.append(") {...}\n");
        }

        builder.append("}");
        System.out.println(builder);
    }
}

输出结果

public class UserService {
	private String userName;
	private String passWord;
	protected String userNo;

	public UserService(String,String,String) {...}
	public UserService(String,String) {...}
	public UserService(String) {...}
	public UserService() {...}

	public String toString() {...}
	public void logout() {...}
	public boolean login(String,String) {...}
}

通过反射机制创建对象(★★★★★)

1. 获取类的字节码
2. 通过字节码获取有/无参构造方法
3. 调用newInstance()方法创建对象

Class<?> aClass = Class.forName("reflectdemo_07.User");			//获取类的字节码

//无参构造方法创建对象
Object o = aClass.newInstance();
System.out.println(o);

//有参构造方法创建对象【推荐】
Constructor<?> newObj = aClass.getDeclaredConstructor(int.class,String.class);
Object obj = newObj.newInstance(1015, "小王");
System.out.println(obj);

反射机制设置/获取字段值(★★★★★)

1. 获取类的字节码
2. 创建对象
3. 获得指定的字段名
4. 使用字段对象.set(Object obj,Object value)方法设置值
5. 使用字段对象.get(Object obj)方法获取值

package reflectdemo_04;

import java.lang.reflect.Field;

/**
 * 通过反射机制设置/获取属性值
 * @Author Nigori
 * @Create 2020/9/2
 */
public class ReflectGetValueTest {

    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("reflectdemo_04.Student");

        Object student = aClass.newInstance();
        Field teacherName = aClass.getDeclaredField("teacherName");
        teacherName.set(student,"王老师");
        System.out.println("teacherName:" + teacherName.get(student));

        Field studentNo = aClass.getDeclaredField("studentNo");
        studentNo.setAccessible(true);      //字段为private时,打破封装,否则在设置/取值值时抛IllegalAccessException
        studentNo.set(student,10051);
        System.out.println("studentNo:" + studentNo.get(student));
    }
}

反射机制调用方法(★★★★★)

1. 获取类的字节码
2. 获得指定方法 【方法名,参数类型】
3. 使用invoke(Object obj, Object... args)调用方法

调用方法四要素:

  • 方法名
  • 对象
  • 实参
  • 返回值
Class<?> aClass = Class.forName("reflectdemo_07.User");			//获取类的字节码
Object obj = aClass.newInstance();			//创建对象

Method show = aClass.getDeclaredMethod("show", int.class);      //获得指定方法
Object retValue = show.invoke(obj,12112);   //方法的调用
System.out.println(retValue);

反射机制获取超类

package reflectdemo_07;

/**
 * @Author Nigori
 * @Create 2020/9/3
 */
public class SetGetTest {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("java.lang.String");

        //获取String类的超类
        Class<?> superclass = aClass.getSuperclass();
        System.out.println(superclass);

        //获取String类实现的所有接口
        Class<?>[] interfaces = aClass.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface.getName());
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值