一文看懂java 反射机制及常用api

概述:
1.反射机制的本质
反射机制通过将硬盘上的class文件加载到内存,让开发人员了解当前的【陌生对象】
     
2.class文件有什么作用:
    class文件是【解释文件】。JVM可以通过【解释文件】了解当前【实例对象】的特征和行为
 
3.class文件在硬盘上的位置:
     1.java prorject 中class文件 在 bin文件下的
     2.web  project  中class文件 在 tomcat---》webapps--->当前工程--->WEB-info-->bin--->classess
4.Class对象的含义

              我们知道,类是对现实的某种事物的抽象定义,而Class是对于类的抽象定义。比如人这个对象。想要写成一个类,需要对人这个对象的属性和行为有所了解。比如人有五官,其中嘴巴能吃饭。眼睛能看东西。这些是我们对人这个对象的认知。并将其定义出来。那么Class就相当与人。Class是Java的类对象。这个类对象都有哪些属性和行为呢?类中有方法(Method),有属性(Field)。类有构造方法(Constract),类有继承(supperClass),其中方法可以让类执行一些行为,构造方法可以获取类的实例。Class就是java类的抽象定义。

 
 
 一:获得某个类的Class引用这个Class是类在内存中的class文件
               通过String指定要获取那个类的Class.注意必须是完整的类名(也就是包名+类名格式)
        获取自定义类的相关信息.这个自定义的类必须要在当前项目中才可以

 

      
           注意:
 Class.forName() 是反射机制【加载】硬盘上的class文件,会创建class文件对象.
 实例对象.getClass() 或者 类名.class 是反射机制【定位】内存中已经存在的class文件
 

 

 二:通过相关Class的引用调用相关方法,得到其方法,属性,构造方法的相关信息:
 
          Class类中的重要API
 
     
 ClassLoadergetClassLoader()                                                                         
          返回该类的类加载器。
 
  1. 获取Field(属性)----->包含属性的修饰符,类型及名称 如:[private int age];
    FieldgetDeclaredField(String name)
              返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
    Field[]getDeclaredFields()
              返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
  2. 获取Method(普通方法)----->包含方法的修饰符,返回值类型,方法名称及抛出的异常 如:[public string getName()];
     

     

    Method

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

              返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方

    Method[]

    getDeclaredMethods()

              返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。


     
  3. 获取Constructor(构造方法)----->包含构造方法的修饰符,方法名称及抛出的异常 如:[public Student()];
 Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes)
          返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
 Constructor<?>[]getDeclaredConstructors()
          返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。

 

 


  例如:(claz是相关类的字节码对象的引用)
                                   
            Constructor[] cons = claz.getConstructors();//
claz.getConstructors()获取的是类中的所有的公开的构造方法

 

 

 

 

             claz.getDeclaredConstructors()//获取类中声声明的构造方法的数组,包括公开的,保护的,缺省的,私有的构造方法     

 

 

 
 
三:不同的操作“对象”,使用不同的API完成想做的功能
 
           在java中把构造方法封装成Constructor类,属性封装成Field类,方法封装成Method类
而他们是继承Class实现AccessibleObject接口(在java.lang.reflect包下)。而这个接口中定义的以下的方法
 
setAccessible(boolean flag)将此对象的 accessible 标志设置为指示的布尔值。
这个方法三个类中都实现了,该方法是设置是否能够访问privat 修饰的属性,方法,构造方法。
                                                                    继承图
               
 
四:反射的代码示例:
 
以下示例一代码是模拟Spring框架中将前台数据转换为实体类的小Demo。   前台数据的key必须保证和实体类中的属性名称绝对一致
 
public class ReflectUtil {
          
        /**
         *   过程:  前台数据------>后台实体类对象
         * 功能:将【添加页面】发送的请求保存到对应的实体类对象中
         * @param req  包含本次请求包含的请求参数
         * @param classObj  与当前【添加页面】对应的【实体类文件】
         * @return
         */
        public static Object parseRequest(HttpServletRequest req,Class classObj)throws Exception{
                        //1. 根据获得【class文件】,创建一个【实例对象】
                           Object obj= classObj.newInstance();
                        //2. 获得本次请求,涉及的所有的【请求参数名称】
                           Enumeration paramArray= req.getParameterNames();
                        // 3.  循环遍历【枚举】
                           while(paramArray.hasMoreElements()){
                                     // 3.1 每一次循环,从【枚举】中获得一个【请求参数名称】   sid
                                     String paramName= (String) paramArray.nextElement();
                                     //3.2 到【class文件】寻找与当前【请求参数名称】相同的【同名属性对象】
                                     //Field fieldObj=classObj.getDeclaredField(paramName);
                                     //表单域中有可能存在非实体类中的属性,所以采用以下方式
                                     Field fieldObj =null;
                                     try{
                                         fieldObj=classObj.getDeclaredField(paramName);
                                     }catch(NoSuchFieldException ex){
                                         System.out.println("属性"+paramName+"在当前类 "+classObj.getName()+"不存在");
                                         continue;
                                     }
                                     fieldObj.setAccessible(true);
                                     // 3.3 读取【请求参数】包含的【内容】
                                     String value = req.getParameter(paramName);
                                     //3.4 读取【同名属性对象】的【数据类型名称】
                                     String typeName=fieldObj.getType().getName();//[int,double,String ,java.util.Date,boolean]
                                      //3.5 根据【同名属性对象】的【数据类型名称】对【请求参数】包含的【内容】进行【类型转换】
                                     Object data=convertType(typeName,value);
                                     // 3.6 将转换后的数据赋值给【同名属性对象】
                                     fieldObj.set(obj, data);//通知JVM,强制为当前【实例对象】中指定的【属性】进行赋值。
                           }
                           //4.  返回赋值好的【实例对象】
                           return obj;
        }

    实例二:模拟数据库数据转换为实体类
       
 /**
         *   过程: 数据库数据------>后台实体类对象
         * 功能:resultSet -----> List
         * @param rs
         * @param xmlPath
         * @return
         */
        public static List convert(ResultSet rs,String xmlPath)throws Exception{
                          //0.局部变量
                           List list = new ArrayList();
                          // 1.将硬盘上【实体类映射文件】加载到内存
                          InputStream in = new FileInputStream(xmlPath);
                          SAXReader saxObj = new SAXReader();
                          Document xmlObj = saxObj.read(in);
                          //2.获得【临时表】包含【内部结构】
                          ResultSetMetaData rsmd= rs.getMetaData();
                          //3.从【实体类映射文件】获得与当前【临时表】对应【实体类文件】
                          String xPath="//@class";
                          Attribute attrObj= (Attribute) xmlObj.selectSingleNode(xPath);
                          String classPath =attrObj.getValue();
                          Class classObj=Class.forName(classPath);
                          // 4.循环【临时表数据行】
                          while(rs.next()){
                                  //4.1,每次循环时,生成一个【实例对象】
                                   Object obj = classObj.newInstance();
                                   //4.2  循环【当前数据行】中的字段信息
                                   for(int col=1;col<=rsmd.getColumnCount();col++){
                                           //4.2.1  每次循环,获得【当前数据行】中一个【字段名称】
                                           String colName = rsmd.getColumnName(col); //DEPTNO
                                           //4.2.2  到  【实体类映射文件】寻找与【字段名称】对应【属性名】
                                           xPath="//property[@colName='"+colName+"']";
                                           Element property= (Element) xmlObj.selectSingleNode(xPath);
                                           String fieldName= property.attributeValue("name"); //departId
                                           //4.2.3  到  【实体类文件】寻找对应的【属性对象】   
                                           Field fieldObj=classObj.getDeclaredField(fieldName);// private int departId;
                                           fieldObj.setAccessible(true);
                                           //4.2.4  读取【当前数据行】,这个【字段名称】关联的数据
                                           String value = rs.getString(colName);
                                           // 4.2.5  根据【属性对象】的数据类型名称,对取得字段内容进行类型转换
                                           String typeName=fieldObj.getType().getName();
                                           Object data=convertType(typeName,value);
                                           // 4.2.6  将转换后的数据添加到【属性对象】     属性对象.set(【实例对象】,data)
                                           fieldObj.set(obj, data);
                                   }
                                   //4.3   将赋值好的 【实例对象】保存到list
                                   list.add(obj);
                          }
                          //5.将list返回  
                          return list;
        }
          //公用的判断数据类型并转换的方法
          private static Object convertType(String typeName,String value)throws Exception{
                  Object data =null;//保存类型转换后的数据
             if("int".equals(typeName)){
                 data = Integer.valueOf(value);
             }else if("double".equals(typeName)){
                 data = Double.valueOf(value);
             }else if("boolean".equals(typeName)){ // "false"  "true"
                 data = Boolean.valueOf(value);
             }else if("java.util.Date".equals(typeName)){
                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                 data=sdf.parse(value);
             }else if("java.lang.String".equals(typeName)){
                 data = value;
             }
             return data;
          }
}

          
 
 Method
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 汽车电子控制单元(ECU)是现代汽车中必不可少的电子设备之一,它负责管理发动机、变速器、车辆稳定性控制系统等多个重要部件。而ECU中的bootloader则是支持ECU软件更新的重要组成部分,它具有一个特殊的启动程序,用于将新的软件加载到ECU中。 ECU bootloader的工作原理主要是将新的软件程序通过CAN总线或其他通信方式,发送到ECU中进行更新。具体步骤如下:首先,ECU bootloader会检查当前系统中的软件版本是否需要更新。如果需要更新,则它会在系统启动时自动进入bootloader模式,并等待接收新的软件程序。接下来,ECU bootloader将通过通信接口接收新的程序,并将其存储在特定的flash存储器中。然后,ECU bootloader会进行程序校验和解压缩等动作,以确保接收到的程序没有任何问题。最后,ECU bootloader将新的程序加载到内存中,并将控制权交给新程序,完成软件更新过程。 在进行ECU bootloader的开发时,需要注意以下几个要点:首先是要选择适当的存储器,并确定软件程序的大小。其次,需要实现通信接口,确定通信协议和数据传输方式。然后,需要设计和实现程序校验和解压缩等安全和稳定性相关的功能。最后,还需要进行一系列的测试和验证,以确保软件更新功能的正确性和可靠性。 总之,ECU bootloader是现代汽车中非常重要的一个电子组件,它支持汽车ECU软件更新,保证了车辆的正常运行和安全。在进行ECU bootloader开发时,需要充分考虑软件大小、通信接口、安全性等方面的因素,确保实现出稳定可靠的功能。 ### 回答2: 汽车电子ECU Bootloader是一种可以更新车辆控制器软件的重要工具,本文将介绍汽车电子ECU Bootloader的工作原理和开发要点。 汽车电子ECU Bootloader的工作原理主要是通过分区管理技术将存储器划分为Bootloader和应用程序两个区域,Bootloader负责车辆控制器的引导和固件更新,而应用程序则实现车辆控制器的各项功能。当车辆控制器出现故障或升级需要时,Bootloader通过CAN总线接受来自外部设备的控制命令,对存储器中的数据进行读写操作,完成软件更新等任务。 开发汽车电子ECU Bootloader需要考虑以下几个要点: 1.安全性:保证Bootloader在更新过程中不会遭到外部攻击或出现故障,同时需要遵守汽车规范和安全标准,确保车辆控制器的安全性和稳定性。 2.可靠性:Bootloader需要对存储器中的数据进行正确的读写操作,避免数据丢失或损坏等可能出现的问题,同时需要实现固件校验技术,确保固件的完整性和正确性。 3.灵活性:Bootloader需要支持多种协议和接口,以适应不同车辆控制器的要求,同时需要支持多种固件格式,以避免与其他系统不兼容的问题。 4.可测试性:Bootloader需要为软件开发人员提供方便的测试和调试工具,以便快速迭代和改进,同时需要支持错误日志和故障诊断技术,以帮助分析和解决问题。 综上所述,汽车电子ECU Bootloader是进行车辆控制器软件更新和管理的重要工具,其开发需要考虑多个要点,包括安全性、可靠性、灵活性和可测试性等,以确保车辆控制器的安全性、稳定性和性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值