当前位置:

首页 > 编程开发 > Java内省机制怎么实现

Java内省机制怎么实现

概念JavaBean在实际编程中,我们常常需要一些用来包装值对象的类,例如Student、Employee、Order,这些类中往往没有业务方法,只是为了把需要处理的实体对象进行封装,有这样的特征:属性都是私有的;有无参的public构造方法;对私有属性根据需要提供公有的getXxx方法以及setXxx方法;比如:属性名称为name,则有getName方法返回属性name值,setName方法设置name值;注意方法的名称通常是get或set加上属性名称,并把属性名称的首字母大写;这些方法称为getter

本文目录

      概念

      JavaBean

      在实际编程中,我们常常需要一些用来包装值对象的类,例如Student、 Employee、Order,这些 类中往往没有业务方法,只是为了把需要处理的实体对象进行封装,有这样的特征:

      • 属性都是私有的;

      • 有无参的public构造方法;

      • 对私有属性根据需要提供公有的getXxx方法以及setXxx方法;

      比如:属性名称为name,则有getName方法返回属性name值, setName方法设置name值;注意方法的名称通常是get或 set加上属性名称,并把属性名称的首字母大写;这些方法称为getters/setters;getters必须有返回值没有方法参数; setter值没有返回值,有方法参数;

      例如下面的例子:

      Java内省机制怎么实现

      符合这些特征的类,被称为JavaBean;

      内省

      内省(Inspector)机制就是基于反射的基础, Java语言对Bean类属性、事件的一种缺省处理方法。

      只要类中有getXXX方法,或者setXXX方法,或者同时有getXXX及setXXX方法,其中getXXX方 法没有方法参数,有返回值; setXXX方法没有返回值,有一个方法参数;那么内省机制就认为 XXX为一个属性;

      例如下面代码

      Employee类中根本没有声明age属性,仅仅是声明了这样的getter和setter.内省机制就认为age是属性

      package com.shixun.introspector;
      
      public class Employee {
          private String name;
          private Double score;
      
          // age将被内省认为是属性
          public int getAge(){
              return 30;
          }
      
          // name将被内省认为是属性
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          // score将被内省认为是属性
          public Double getScore() {
              return score;
          }
      
          public void setScore(Double score) {
              this.score = score;
          }
      
          public static void main(String[] args) {
              
      
          }
      }

      相关API

      与Java内省有关的主要类及接口有:

      • java.beans.Introspector类: 为获得JavaBean属性、事件、方法提供了标准方法;通常使用其中的getBeanInfo方法返回BeanInfo对象;

      • Java.beans.BeanInfo接口:不能直接实例化,通常通过Introspector类返回该类型对象,提供了返回属性描述符对象(PropertyDescriptor)、方法描述符对象(MethodDescriptor) 、 bean描述符(BeanDescriptor)对象的方法;

      • Java.beans.PropertyDescriptor类:用来描述一个属性,该属性有getter及setter方法;

      可以使用PropertyDescriptor类的方法获取属性相关的信息,例如getName方法返回属性的名字:

      PropertyDescriptor类中定义了方法可以获取该属性的getter和setter方法

      方法方法描述
      Method getReadMethod()回属性对应的getter方法对象;
      Method getWriteMethod()回属性对应的setter方法对象;

      下面我们来用代码深入探究一下:

      代码案例:获取属性相关信息

      Employee如上面代码所示,继续编写主函数进行测试

      首先用BeanInfo接口获取BeanInfo的对象,再通过BeanInfo对象获取PropertyDescriptor属性描述

       //获取BeanInfo的对象
       BeanInfo employeeBeanInfo = Introspector.getBeanInfo(Employee.class);
       //通过BeanInfo对象获取PropertyDescriptor属性描述
       PropertyDescriptor[] propertyDescriptors = employeeBeanInfo.getPropertyDescriptors();
       System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");
       Arrays.stream(propertyDescriptors).forEach(f->{
           System.out.println("====================================");
           System.out.println("属性名:"+f.getName());
           System.out.println("类型:"+f.getPropertyType());
           System.out.println("get方法:"+f.getReadMethod());
           System.out.println("set方法:"+f.getWriteMethod());
       });
      
      // 或者用增强for
      System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");
      for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
      	System.out.println("====================================");
          System.out.println("名字:" + propertyDescriptor.getName());
          System.out.println("类型:" + propertyDescriptor.getPropertyType());
          System.out.println("get方法:" + propertyDescriptor.getReadMethod());
          System.out.println("set方法:" + propertyDescriptor.getWriteMethod());
      }

      运行结果如下:

      Java内省机制怎么实现

      我们也可以通过反射调用这里获取的get或set方法

      //创建Employee的对象
      Class clazz = Class.forName("com.shixun.introspector.Employee");
      Object employee = clazz.newInstance();
      
      //遍历属性描述对象
      for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
          //打印属性名称
          System.out.println(propertyDescriptor.getName());
          //判断属性名称是不是name
          if (propertyDescriptor.getName().equals("name")) {
              //setter方法
              Method writeMethod = propertyDescriptor.getWriteMethod();
              //调用setName方法
              writeMethod.invoke(employee, "jack");
              //getter方法
              Method readMethod = propertyDescriptor.getReadMethod();
              //调用getName方法
              Object nameValue = readMethod.invoke(employee);
              System.out.println("name属性的值为:" + nameValue);
          }
          //判断属性名称是否为score
          if (propertyDescriptor.getName().equals("score")) {
              //setter方法
              Method scoreWriteMethod = propertyDescriptor.getWriteMethod();
              //调用setScore方法
              scoreWriteMethod.invoke(employee, new Double(3000));
              //getter方法
              Method scoreReadMethod = propertyDescriptor.getReadMethod();
              Object scoreValue = scoreReadMethod.invoke(employee);
              System.out.println("score属性的值为:" + scoreValue);
          }
      }
      System.out.println("当前对象的信息:"+employee.toString());

      运行结果如下所示:

      Java内省机制怎么实现

      全部代码附在最下方!!!!!!

      内省属性的注意事项

      • 很多框架都使用了内省机制检索对象的属性,定义属性名字时,名字最好起码以两个小写字母开头,例如stuName,而不要使用sName,某些情况下,可能会导致检索属性失败;

      • 内省机制检索属性时,是根据getter和setter方法确认属性名字,而不是根据类里声明的成员变量名称决定;

      完整代码

      package com.shixun.introspector;
      
      import java.beans.BeanInfo;
      import java.beans.IntrospectionException;
      import java.beans.Introspector;
      import java.beans.PropertyDescriptor;
      import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;
      import java.util.Arrays;
      
      public class Employee {
          private String name;
          private Double score;
      
          // age将被内省认为是属性
          public int getAge() {
              return 30;
          }
      
          // name将被内省认为是属性
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          // score将被内省认为是属性
          public Double getScore() {
              return score;
          }
      
          public void setScore(Double score) {
              this.score = score;
          }
      
          @Override
          public String toString() {
              return "Employee{" +
                      "name='" + name + '\'' +
                      ", score=" + score +
                      '}';
          }
      
          public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InstantiationException, InvocationTargetException {
              //获取BeanInfo的对象
              BeanInfo employeeBeanInfo = Introspector.getBeanInfo(Employee.class);
      
              //通过BeanInfo对象获取PropertyDescriptor属性描述
              PropertyDescriptor[] propertyDescriptors = employeeBeanInfo.getPropertyDescriptors();
      //        System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");
      //        Arrays.stream(propertyDescriptors).forEach(f->{
      //            System.out.println("====================================");
      //            System.out.println("属性名:"+f.getName());
      //            System.out.println("类型:"+f.getPropertyType());
      //            System.out.println("get方法:"+f.getReadMethod());
      //            System.out.println("set方法:"+f.getWriteMethod());
      //        });
      //
      //
      //
      //        System.out.println("通过Inspector内省机制获取JavaBean属性======= 打印所有信息 ====================");
      //
      //        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
      //            System.out.println("名字:" + propertyDescriptor.getName());
      //            System.out.println("类型:" + propertyDescriptor.getPropertyType());
      //            System.out.println("get方法:" + propertyDescriptor.getReadMethod());
      //            System.out.println("set方法:" + propertyDescriptor.getWriteMethod());
      //        }
      
              //创建Employee的对象
              Class clazz = Class.forName("com.shixun.introspector.Employee");
              Object employee = clazz.newInstance();
      
              //遍历属性描述对象
              for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                  //打印属性名称
                  System.out.println(propertyDescriptor.getName());
                  //判断属性名称是不是name
                  if (propertyDescriptor.getName().equals("name")) {
                      //setter方法
                      Method writeMethod = propertyDescriptor.getWriteMethod();
                      //调用setName方法
                      writeMethod.invoke(employee, "jack");
                      //getter方法
                      Method readMethod = propertyDescriptor.getReadMethod();
                      //调用getName方法
                      Object nameValue = readMethod.invoke(employee);
                      System.out.println("name属性的值为:" + nameValue);
                  }
                  //判断属性名称是否为score
                  if (propertyDescriptor.getName().equals("score")) {
                      //setter方法
                      Method scoreWriteMethod = propertyDescriptor.getWriteMethod();
                      //调用setScore方法
                      scoreWriteMethod.invoke(employee, new Double(3000));
                      //getter方法
                      Method scoreReadMethod = propertyDescriptor.getReadMethod();
                      Object scoreValue = scoreReadMethod.invoke(employee);
                      System.out.println("score属性的值为:" + scoreValue);
                  }
              }
      
              System.out.println("当前对象的信息:"+employee.toString());
          }
      }
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Java
      相关文章 更多
      Java单元测试入门:使用JUnit 5编写第一个测试用例
      Java单元测试入门:使用JUnit 5编写第一个测试用例

      面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

      Java变量未初始化报错解析:局部变量与成员变量默认值差异
      Java变量未初始化报错解析:局部变量与成员变量默认值差异

      深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

      详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

      Java中final与static final常量的定义及初始化规则
      Java中final与static final常量的定义及初始化规则

      深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

      Java抽象方法与接口方法的区别及选型建议
      Java抽象方法与接口方法的区别及选型建议

      深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

      Java实现HTTP请求与JSON解析的完整代码示例
      Java实现HTTP请求与JSON解析的完整代码示例

      本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

      Java递归出现StackOverflowError的原因分析及栈空间优化方案
      Java递归出现StackOverflowError的原因分析及栈空间优化方案

      详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

      Java空指针异常(NPE)的代码排查与修复实例
      Java空指针异常(NPE)的代码排查与修复实例

      针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

      selenium上传文件教程本地文件路径设置方法
      selenium上传文件教程本地文件路径设置方法

      深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

      针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。