当前位置: 首页 > article >正文

Java反射学习(4)(“反射“机制获取成员方法及详细信息(Method类))

目录

一、基本引言。

(1)基本内容回顾。

(2)本篇博客的核心内容——基本介绍。

二、Java中使用"反射"机制获取成员方法及内部的详细信息。

(1)"反射"机制获取成员方法及详细信息的基本概念。

(2)利用Java的对象机制进行封装。(Method类)

1、构造方法。(Constructor类)

2、字段(成员变量)。(Field类)

3、成员方法。(Method类)

(3)操作成员方法的类"Method"相关的操作方法。

1、Class类中用于获取成员方法(返回Method类对象)的常用方法。

2、"Method"类中用于创建对象的方法。

3、"Method"类对象的重要且常用的操作方法。

(4)有关"Method"类的核心方法的操作演示。

<1>第一步。获取对应Student类的字节码文件对象(Class类)。

<2>第二步。通过Class对象获取Student类中对应成员方法"Method"对象。

<3>第三步。通过获取的成员方法"Method"对象获取其内部详细信息。


一、基本引言。

(1)基本内容回顾。

  • 前面博客学习《Class类对象的三种实例化方式及使用时机利用"反射"获取构造方法及详细信息——>Constructor类相关操作》Java反射学习(2)(“反射“机制获取构造方法及内部信息(Constructor类))-CSDN博客
  • 上篇博客学习《利用"反射"获取成员变量及详细信息——>Field类的相关操作》
  • Java反射学习(3)(“反射“机制获取成员变量及详细信息(Field类))-CSDN博客

(2)本篇博客的核心内容——基本介绍。

  • 本篇博客的内容围绕:通过"反射"机制(.class字节码文件——>Class类对象)获取成员方法及详细信息——>Method类的相关操作。
  • 原理图如下所示。

二、Java中使用"反射"机制获取成员方法及内部的详细信息。

(1)"反射"机制获取成员方法及详细信息的基本概念。
  • 在Java中,反射是一种强大的机制,它允许程序在运行时访问、检查和修改它自己的结构,包括类、接口、字段和方法。
  • 使用反射可以动态地调用方法、访问字段、构造对象等。

  • 在介绍如何使用"反射"来获取类中(.class字节码文件)的成员变量及其详细信息的基本步骤之前需要先了解类"Method"。

(2)利用Java的对象机制进行封装。(Method类)

  • 基于"Java万事万物皆对象"的机制。
  • 使用.class(字节码文件)——(字节码文件对象)"Class"类对象获取对应类的信息。

1、构造方法。(Constructor类)
  • 封装构造方法的实体类"Constructor"。(在引言中已经提及)

2、字段(成员变量)。(Field类)
  • 封装成员变量的实体类"Field"。(在引言中已经提及)

3、成员方法。(Method类)
  • 封装成员方法的实体类"Method"。(本篇博客讨论的重点)

(3)操作成员方法的类"Method"相关的操作方法。
1、Class类中用于获取成员方法(返回Method类对象)的常用方法。

  • 简单识别法:带"s"的获取的值不只一个带"declared"无视访问修饰符权限全部拿到
  • 注意:个别方法可以拿到父类的所有公共权限(public)的方法
方法声明功能描述
Method [] getMethods();

返回所有公共成员方法对象的数组

包括继承的

Method [] getDeclaredMethods();

返回所有成员方法(包括private)对象的数组

不包括继承的

Method getMethod

(String name, Class<?>...parameterTypes)

返回单个公共(public)成员方法对象


parameterType:表示指定成员方法的参数类型——对应的类名.class(字节码文件对象)。

Method getDeclaredMethod(String name, Class<?>... parameterTypes)

返回单个成员方法(包括private)对象


parameterType:表示指定成员方法的参数类型——对应的类名.class(字节码文件对象)。

2、"Method"类中用于创建对象的方法。
方法声明功能描述

Object invoke(Object obj,Object...args);

(运行方法)

这个方法允许你在运行时调用任意一个已经通过反射获取到的Java方法

参数一:用obj对象调用该方法。


参数二:调用方法的传递的参数(如果没有就不写!


返回值:方法的返回值(如果没有就不写!

3、"Method"类对象的重要且常用的操作方法。
方法声明功能描述
getModifiers();获取成员方法的权限修饰符。
getName();获取成员方法的名称。
getParameterTypes();获取成员方法的全部参数的类型。
getReturnType();获取成员方法的返回值类型。
getExceptionType();获取成员方法的抛出的全部异常类型。
newInstance(Object ...initargs)通过反射调用类中的成员方法。
(4)有关"Method"类的核心方法的操作演示。
  • 提供一个实体类:Student。

  • Student类提供二个成员变量。
  • 访问权限为private的成员变量name。
  • 访问权限为private的成员变量age。
  • 提供正常的构造方法(无参构造与有参构造方法)、getter与setter方法、toString()方法。

  • 提供4个成员方法。其中两个成员方法是重载(参数个数不一致)。
  • 访问权限为public的(无返回值)(无参)成员方法sleep()。里面打印控制台信息输出。
  • 访问权限为private的(无返回值)成员方法eat(String food)。里面打印控制台信息输出。
  • 访问权限为private的(无返回值)成员方法eat(String food,int num)。里面打印控制台信息输出。
  • 访问权限为private的(有返回值)成员方法study(String context)。里面打印控制台信息输出。

  • 最后会提供一个测试类(Main类)进行核心方法操作的测试。
<1>第一步。获取对应Student类的字节码文件对象(Class类)。
package com.fs.test;
 
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
    }
}
<2>第二步。通过Class对象获取Student类中对应成员方法"Method"对象。
  • 通过字节码文件对象(Class对象)获取所有公共的(public)成员方法。
  • getMethods()方法除了获取所有的公共成员方法外,还会获取到父类的公共成员方法。
package com.fs.test;

import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");

        //通过字节码文件对象(Class对象)获取所有公共的(public)成员方法
        //还会获取到父类的成员方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}


  • 通过字节码文件对象(Class对象)获取所有成员方法。(包括private修饰的成员方法)

  • getDeclaredMethods()方法:虽然可以获取子类的所有方法,但无法获取父类的方法。

package com.fs.test;

import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");

        //通过字节码文件对象(Class对象)获取所有的成员方法
        //无法获取到父类的成员方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}


  • 通过字节码文件对象(Class对象)获取单个成员方法。
  • String name, Class<?>...parameterTypes:方法名与参数类型(类名.class)。
  • invoke()方法是Java反射API中的一个方法,它属于java.lang.reflect.Method类。这个方法允许你在运行时调用任意一个已经通过反射获取到的Java方法
  • 使用反射获取到的某个类的成员方法再调用——使用invoke()。若成员方法无返回值也可以不写(不接收)。
package com.fs.test;

import com.fs.entity.Student;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取单个无参成员方法(public)
        Method sleep = clazz.getMethod("sleep");
        Student s = new Student();
        //使用反射调用方法
        sleep.invoke(s);
    }
}


  • 通过字节码文件对象(Class对象)获取单个成员(可以获取private)方法。


package com.fs.test;

import com.fs.entity.Student;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取单个有参成员方法(private)
        // 获取有参重载方法(eat)1个参数
        Method eat1 = clazz.getDeclaredMethod("eat", String.class);
        //临时取消访问权限检查(因为是private权限的方法)
        eat1.setAccessible(true);
        eat1.invoke(new Student(), "苹果");
        System.out.println("----------------------------------------------------------");
        //获取有参重载方法(eat)2个参数
        Method eat2 = clazz.getDeclaredMethod("eat", String.class, int.class);
        //临时取消访问权限检查(因为是private权限的方法)
        eat2.setAccessible(true);
        eat2.invoke(new Student(), "苹果", 10);
    }
}


<3>第三步。通过获取的成员方法"Method"对象获取其内部详细信息。

  • 通过字节码文件对象(Class对象)获取某个指定成员方法的访问权限修饰符。
package com.fs.test;

import com.fs.entity.Student;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取单个无参成员方法(public)
        Method sleep = clazz.getMethod("sleep");
        int modifiers = sleep.getModifiers();
        System.out.println(modifiers);
        System.out.println("==================================================");
        //获取单个有参成员方法(private)
        // 获取有参重载方法(eat)1个参数
        Method eat1 = clazz.getDeclaredMethod("eat", String.class);
        int modifiers01 = eat1.getModifiers();
        System.out.println(modifiers01);
        System.out.println("==================================================");
        //获取有参重载方法(eat)2个参数
        Method eat2 = clazz.getDeclaredMethod("eat", String.class, int.class);
        int modifiers02 = eat2.getModifiers();
        System.out.println(modifiers02);

    }
}



  • 通过字节码文件对象(Class对象)获取某个指定成员方法的名称。
package com.fs.test;

import com.fs.entity.Student;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取某个指定的成员方法对象
        Method study = clazz.getDeclaredMethod("study", String.class);
        //获取成员方法的方法名
        String methodName = study.getName();
        System.out.println(methodName);

    }
}


  • 通过字节码文件对象(Class对象)获取某个指定成员方法的形参个数、形参类型或者获取到参数的数组对象!
package com.fs.test;

import com.fs.entity.Student;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取某个指定的成员方法对象
        Method eat = clazz.getDeclaredMethod("eat", String.class, int.class);
        //获取某个指定的成员方法对象参数个数
        System.out.println("eat()方法的参数个数:"+eat.getParameterCount());
        System.out.println("===========================================");
        //获取某个指定的成员方法对象参数类型
        Class<?>[] parameterTypes = eat.getParameterTypes();
        for (Class<?> parameterType : parameterTypes) {
            System.out.println("参数类型:"+parameterType);
        }
        System.out.println("===========================================");
        //直接获取某个指定的成员方法对象参数对象
        Parameter[] parameters = eat.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }

    }
}


  • 通过字节码文件对象(Class对象)获取某个指定成员方法的抛出的所有异常!
package com.fs.test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取某个指定的成员方法对象
        Method study = clazz.getDeclaredMethod("study", String.class);
        Class<?>[] exceptionTypes = study.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println("异常类型:"+exceptionType);
        }
    }
}


  • 通过字节码文件对象(Class对象)获取并允许某个指定成员方法。
  • 使用方法:Object invoke(Object obj,Object...args);
  • 参数1:表示调用该方法的对象。
  • 参数2:指定成员方法的形参。(如果是空参,则可以不写)
  • 方法的返回值:如果是void,则也可以不写(不必理会)。
  • 调用方法如果访问权限修饰符是private,就要临时取消访问权限检查(方法setAccessaible()


package com.fs.test;

import com.fs.entity.Student;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.通过Student类的全限定类名获取class字节码文件对象
        Class<?> clazz = Class.forName("com.fs.entity.Student");
        //获取某个指定的成员方法对象
        Method studyMethod = clazz.getDeclaredMethod("study", String.class);
        //创建Student类对象。因为要使用该类对象才能调用该成员方法,所以需要创建对象
        Student s = new Student();
        //临时取消访问权限检验
        studyMethod.setAccessible(true);
        //调用invoke()方法
        //注意study()方法有返回值
        String returnStr = (String) studyMethod.invoke(s, "java");
        System.out.println(returnStr);
    }
}


http://www.kler.cn/a/452197.html

相关文章:

  • Redis-十大数据类型
  • 【Nginx系列】---Nginx配置tcp转发
  • Modbus数据网关在制造企业的应用与效果
  • 鸿蒙开发:了解帧动画
  • Y3地图制作1:水果缤纷乐、密室逃脱
  • 62.基于SpringBoot + Vue实现的前后端分离-驾校预约学习系统(项目+论文)
  • 用于航空发动机故障诊断的深度分层排序网络
  • [项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结
  • 宠物行业的出路:在爱与陪伴中寻找增长新机遇
  • PDF在线预览实现:如何使用vue-pdf-embed实现前端PDF在线阅读
  • Jenkins 构建流水线
  • 实训项目-人力资源管理系统-1Company子模块
  • 云手机+YouTube:改变通信世界的划时代技术
  • 前端学习:从零开始做一个前端开源项目
  • Python+OpenCV系列:【打卡系统-需求分析】需求大剖析,考勤革命开启!
  • langchain使用FewShotPromptTemplate出现KeyError的解决方案
  • 12.24周二F34-Day35打卡
  • 【vue】css模拟玻璃球体效果(带高光)
  • Opencv实现图像的腐蚀、膨胀及开、闭运算
  • 舵机原理介绍 简洁讲解面向实战 非阻塞式驱动代码, arduino
  • 重温设计模式--外观模式
  • PromptGIP:Unifying lmage Processing as Visual Prompting Question Answering
  • gesp(二级)(12)洛谷:B3955:[GESP202403 二级] 小杨的日字矩阵
  • QT从入门到精通(三)——实现文件列表遍历的图像浏览器
  • 【Linux编程】TcpServer 类的设计与实现:构建高性能的 TCP 服务器(二)
  • 《实战AI智能体》魔搭多 Agent 模式(一)