Java反射机制的简单学习

news/2024/7/5 5:30:42

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

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

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

Java反射的应用

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

Java反射相关API

  java.lang包下

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

  java.lang.reflect包下

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

    -Method 类 : 代表类的方法

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

反射的类类型:Class

假设我们有一个Role类

 1 package _Venom_.reflection;
 2 
 3 public class Role {
 4     
 5     private String name;
 6     private String type;
 7     
 8     //Constructors
 9     public Role(){
10         System.out.println("Constructor Role() is invoking!");
11     }
12     
13     private Role(String _name){
14         this.name = _name;
15         System.out.println("Constructor Role(String _name) is invoking!");
16     }
17 
18     
19     //get and set method
20     public String getName() {
21         return name;
22     }
23 
24     public void setName(String name) {
25         this.name = name;
26     }
27 
28     public String getType() {
29         return type;
30     }
31 
32     public void setType(String type) {
33         this.type = type;
34     }
35 
36     //override the toString method to show the class
37     @Override
38     public String toString() {
39         // TODO Auto-generated method stub
40         return "This is a role called " + this.name;
41     }
42     
43 }

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

获取方式

说明

示例

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一下我的学习历程。

    

转载于:https://www.cnblogs.com/Venom/p/3280707.html


http://www.niftyadmin.cn/n/3051402.html

相关文章

进程系统调用函数

fork pid_t fork(void); 返回值&#xff1a; 0&#xff1a; 子进程 子进程 PID(大于0 的整数)&#xff1a; 父进程 getpid() getppid() 转载于:https://www.cnblogs.com/fengyang66/p/6021100.html

Vue项目之IE下打开页面是空白

原因是&#xff1a;Babel 默认只转换新的 JavaScript 句法&#xff08;syntax&#xff09;&#xff0c;而不转换新的 API &#xff0c;比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象&#xff0c;以及一些定义在全局对象上的方法&#xff0…

7.1 简单线性回归 (Simple Linear Regression)上

0. 前提介绍&#xff1a; 为什么需要统计量&#xff1f; 统计量&#xff1a;描述数据特征 0.1 集中趋势衡量 0.1.1均值&#xff08;平均数&#xff0c;平均值&#xff09;&#xff08;mean&#xff09; {6, 2, 9, 1, 2} (6 2 9 1 2) / 5 20 / 5 4 0.1.2中位数 &#xff…

storm安装(单机和集群)

storm安装单机和集群单机安装下载解压这里不做修改&#xff0c;直接启动访问UI界面集群搭建修改storm.yaml 配置文件将程序拷贝到其他节点启动服务单机安装 下载 https://storm.apache.org/在官方网站下载storm即可 解压 解压到指定文件夹/opt/topology/service tar zxf s…

Sentry--错误日志收集框架

简介Sentry’s real-time error tracking gives you insight into production deployments and information to reproduce and fix crashes.---官网介绍Sentry是一个实时事件日志记录和汇集的日志平台&#xff0c;其专注于错误监控&#xff0c;以及提取一切事后处理所需的信息。…

Start with...Connect By

Start with...Connect By子句递归查询一般用于一个表维护树形结构的应用。创建示例表&#xff1a;CREATE TABLE TBL_TEST(ID NUMBER,NAME VARCHAR2(100 BYTE),PID NUMBER DEFAULT 0);插入测试数据&#xff1a;INSERT INTO TBL_TEST(ID,…

linux下使用正确的用户名密码,本地无法连接mysql

问题现象&#xff1a; Linux系统为CentOS 7.0 64位&#xff0c;通过IP远程mysql时&#xff0c;可以正常访问&#xff0c;确定账号密码没有问题。但是本地连接mysql时&#xff0c;提示ERROR 1045 (28000): Access denied for user RnE0LXGMQhHNlocalhost (using password: YES)&…

IPV6基本知识

IPV6基本知识基本概念基本概念 IPv6是由八组&#xff0c;每组四位16进制数字组成&#xff0c;每组之间由"&#xff1a;"来分隔。 简单的例子&#xff1a; 2610:00f8:0c34:67f9:0200:83ff:fe94:4c36&#xff0c;每个“&#xff1a;”前后都是4位16进制的数字&#x…