java-反射机制

概念

Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。
在这里插入图片描述

Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect包。

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。
  • 生成动态代理。
Class labelCls = label1.getClass();    // label1为 JLabel 类的对象

利用 Class 类的对象 labelCls 可以访问 labelCls 对象的描述信息、JLabel 类的信息以及基类 Object 的信息

类型访问方法返回值类型说明
包路径getPackage()Package 对象获取该类的存放路径
类名称getName()String 对象获取该类的名称
继承类getSuperclass()Class 对象获取该类继承的类
实现接口getlnterfaces()Class 型数组获取该类实现的所有接口
构造方法getConstructors()Constructor 型数组获取所有权限为 public 的构造方法
getDeclaredContruectors()Constructor 对象获取当前对象的所有构造方法
方法getMethods()Methods 型数组获取所有权限为 public 的方法
getDeclaredMethods()Methods 对象获取当前对象的所有方法
成员变量getFields()Field 型数组获取所有权限为 public 的成员变量
getDeclareFileds()Field 对象获取当前对象的所有成员变量
内部类getClasses()Class 型数组获取所有权限为 public 的内部类
getDeclaredClasses()Class 型数组获取所有内部类
内部类的声明类getDeclaringClass()Class 对象如果该类为内部类,则返回它的成员类,否则返回 null

Java通过反射访问构造方法

  • getConstructors()
  • getConstructor(Class<?>…parameterTypes)
  • getDeclaredConstructors()
  • getDeclaredConstructor(Class<?>…parameterTypes)
方法名称说明
isVarArgs()查看该构造方法是否允许带可变数量的参数,如果允许,返回 true,否则返回 false
getParameterTypes()按照声明顺序以 Class 数组的形式获取该构造方法各个参数的类型
getExceptionTypes()以 Class 数组的形式获取该构造方法可能抛出的异常类型
newInstance(Object … initargs)通过该构造方法利用指定参数创建一个该类型的对象,如果未设置参数则表示 采用默认无参的构造方法
setAccessiable(boolean flag)如果该构造方法的权限为 private,默认为不允许通过反射利用 netlnstance() 方法创建对象。如果先执行该方法,并将入口参数设置为 true,则允许创建对 象
getModifiers()获得可以解析出该构造方法所采用修饰符的整数
int modifiers = con.getModifiers();    // 获取构造方法的修饰符整数
boolean isPublic = Modifier.isPublic(modifiers);    // 判断修饰符整数是否为public 
string allModifiers = Modifier.toString(modifiers);
静态方法名称说明
isStatic(int mod)如果使用 static 修饰符修饰则返回 true,否则返回 false
isPublic(int mod)如果使用 public 修饰符修饰则返回 true,否则返回 false
isProtected(int mod)如果使用 protected 修饰符修饰则返回 true,否则返回 false
isPrivate(int mod)如果使用 private 修饰符修饰则返回 true,否则返回 false
isFinal(int mod)如果使用 final 修饰符修饰则返回 true,否则返回 false
toString(int mod)以字符串形式返回所有修饰符
public class Test01 {
    public static void main(String[] args) {
        // 获取动态类Book
        Class book = Book.class;
        // 获取Book类的所有构造方法
        Constructor[] declaredContructors = book.getDeclaredConstructors();
        // 遍历所有构造方法
        for (int i = 0; i < declaredContructors.length; i++) {
            Constructor con = declaredContructors[i];
            // 判断构造方法的参数是否可变
            System.out.println("查看是否允许带可变数量的参数:" + con.isVarArgs());
            System.out.println("该构造方法的入口参数类型依次为:");
            // 获取所有参数类型
            Class[] parameterTypes = con.getParameterTypes();
            for (int j = 0; j < parameterTypes.length; j++) {
                System.out.println(" " + parameterTypes[j]);
            }
            System.out.println("该构造方法可能拋出的异常类型为:");
            // 获取所有可能拋出的异常类型
            Class[] exceptionTypes = con.getExceptionTypes();
            for (int j = 0; j < exceptionTypes.length; j++) {
                System.out.println(" " + parameterTypes[j]);
            }
            // 创建一个未实例化的Book类实例
            Book book1 = null;
            while (book1 == null) {
                try { // 如果该成员变量的访问权限为private,则拋出异常
                    if (i == 1) {
                        // 通过执行带两个参数的构造方法实例化book1
                        book1 = (Book) con.newInstance("Java 教程", 10);
                    } else if (i == 2) {
                        // 通过执行默认构造方法实例化book1
                        book1 = (Book) con.newInstance();
                    } else {
                        // 通过执行可变数量参数的构造方法实例化book1
                        Object[] parameters = new Object[] { new String[] { "100", "200" } };
                        book1 = (Book) con.newInstance(parameters);
                    }
                } catch (Exception e) {
                    System.out.println("在创建对象时拋出异常,下面执行 setAccessible() 方法");
                    con.setAccessible(true); // 设置允许访问 private 成员
                }
            }
            book1.print();
            System.out.println("=============================\n");
        }
    }
}

Java通过反射执行方法

动态获取一个对象方法的信息,首先需要通过下列方法之一创建一个 Method 类型的对象或者数组。

  • getMethods()
  • getMethods(String name,Class<?> …parameterTypes)
  • getDeclaredMethods()
  • getDeclaredMethods(String name,Class<?>…parameterTypes)
静态方法名称说明
getName()获取该方法的名称
getParameterType()按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getReturnType()以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes()以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object…args)利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs()查看该方法是否允许带有可变数量的参数,如果允许返回 true,否则返回 false
getModifiers()获得可以解析出该方法所采用修饰符的整
public class Test02 {
    public static void main(String[] args) {
        // 获取动态类Book1
        Book1 book = new Book1();
        Class class1 = book.getClass();
        // 获取Book1类的所有方法
        Method[] declaredMethods = class1.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            Method method = declaredMethods[i];
            System.out.println("方法名称为:" + method.getName());
            System.out.println("方法是否带有可变数量的参数:" + method.isVarArgs());
            System.out.println("方法的参数类型依次为:");
            // 获取所有参数类型
            Class[] methodType = method.getParameterTypes();
            for (int j = 0; j < methodType.length; j++) {
                System.out.println(" " + methodType[j]);
            }
            // 获取返回值类型
            System.out.println("方法的返回值类型为:" + method.getReturnType());
            System.out.println("方法可能抛出的异常类型有:");
            // 获取所有可能抛出的异常
            Class[] methodExceptions = method.getExceptionTypes();
            for (int j = 0; j < methodExceptions.length; j++) {
                System.out.println(" " + methodExceptions[j]);
            }
            boolean isTurn = true;
            while (isTurn) {
                try { // 如果该成员变量的访问权限为private,则抛出异常
                    isTurn = false;
                    if (method.getName().equals("staticMethod")) { // 调用没有参数的方法
                        method.invoke(book);
                    } else if (method.getName().equals("publicMethod")) { // 调用一个参数的方法
                        System.out.println("publicMethod(10)的返回值为:" + method.invoke(book, 10));
                    } else if (method.getName().equals("protectedMethod")) { // 调用两个参数的方法
                        System.out.println("protectedMethod(\"10\",15)的返回值为:" + method.invoke(book, "10", 15));
                    } else if (method.getName().equals("privateMethod")) { // 调用可变数量参数的方法
                        Object[] parameters = new Object[] { new String[] { "J", "A", "V", "A" } };
                        System.out.println("privateMethod()的返回值为:" + method.invoke(book, parameters));
                    }
                } catch (Exception e) {
                    System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法");
                    method.setAccessible(true); // 设置为允许访问private方法
                    isTurn = true;
                }
            }
            System.out.println("=============================\n");
        }
    }
}

Java通过反射访问成员变量

通过下列任意一个方法访问成员变量时将返回 Field 类型的对象或数组。

  • getFields()
  • getField(String name)
  • getDeclaredFields()
  • getDeclaredField(String name)
object.getDeciaredField("price");
方法名称说明
getName()获得该成员变量的名称
getType()获取表示该成员变量的 Class 对象
get(Object obj)获得指定对象 obj 中成员变量的值,返回值为 Object 类型
set(Object obj, Object value)将指定对象 obj 中成员变量的值设置为 value
getlnt(0bject obj)获得指定对象 obj 中成员类型为 int 的成员变量的值
setlnt(0bject obj, int i)将指定对象 obj 中成员变量的值设置为 i
setFloat(Object obj, float f)将指定对象 obj 中成员变量的值设置为 f
getBoolean(Object obj)获得指定对象 obj 中成员类型为 boolean 的成员变量的值
setBoolean(Object obj, boolean b)将指定对象 obj 中成员变量的值设置为 b
getFloat(Object obj)获得指定对象 obj 中成员类型为 float 的成员变量的值
setAccessible(boolean flag)此方法可以设置是否忽略权限直接访问 private 等私有权限的成员变量
getModifiers()获得可以解析出该方法所采用修饰符的整数
public class Test03 {
    public static void main(String[] args) {
        Book2 book = new Book2();
        // 获取动态类Book2
        Class class1 = book.getClass();
        // 获取Book2类的所有成员
        Field[] declaredFields = class1.getDeclaredFields();
        // 遍历所有的成员
        for(int i = 0;i < declaredFields.length;i++) {    
            // 获取类中的成员变量
            Field field = declaredFields[i];
            System.out.println("成员名称为:" + field.getName());
            Class fieldType = field.getType();
            System.out.println("成员类型为:" + fieldType);
            boolean isTurn = true;
            while(isTurn) {
                try {    
                    // 如果该成员变量的访问权限为private,则抛出异常
                    isTurn = false;
                    System.out.println("修改前成员的值为:" + field.get(book));
                    // 判断成员类型是否为int
                    if(fieldType.equals(int.class)) {
                        System.out.println("利用setInt()方法修改成员的值");
                        field.setInt(book, 100);
                    } else if(fieldType.equals(float.class)) {    
                        // 判断成员变量类型是否为float
                        System.out.println("利用setFloat()方法修改成员的值");
                        field.setFloat(book, 29.815f);
                    } else if(fieldType.equals(boolean.class)) {    
                        // 判断成员变量是否为boolean
                        System.out.println("利用setBoolean()方法修改成员的值");
                        field.setBoolean(book, true);
                    } else {
                        System.out.println("利用set()方法修改成员的值");
                        field.set(book, "Java编程");
                    }
                    System.out.println("修改后成员的值为:" + field.get(book));
                } catch (Exception e) {
                    System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法");
                    field.setAccessible(true);
                    isTurn = true;
                }
            }
            System.out.println("=============================\n");
        }
    }
}

Java在远程方法调用中运用反射机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值