• Java关于反射


    反射的概念:JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

    通俗一些 就是说Java通过反射能够创建类的对象,使用类中的方法以及获取类中的属性信息

    想写这篇博客缘由是最近做项目时,发现前后台交互,前端(vue)传过来的空对象,后台(springboot)获取后使用 obj == null 是无法判断出来的,其实obj里面的属性对应的属性值都为null, 当对象中嵌套对象再被调用时会抛出空指针异常!!!

    eg:

    Vue前端发送请求代码:     // 下一步 按钮(转到基本计划页面)

        nextStep: function () {
          var inputForm = {
    'proposalStk': {},

    SpringBoot 后台部分代码:

        @RequestMapping(value = "/ProposalFlowBasicPlan", method = RequestMethod.POST)
        public  DataResult  ProposalFlowBasicPlan(HttpServletRequest request,
                @RequestBody(required = false) ProposalFlowBasicPlanVO proposalFlowBasicPlanVO) {

           ProposalStk proposalStk = proposalFlowBasicPlanVO.getProposalStk();//从入参中获取 proposalStk 对象,这里获取到的 proposalStk 对象是非 NULL 的

         if(proposalStk != null){

             //if(proposalStk.getStkInsured() != null){  //注释掉这句话时,下面会抛出NullPointerException
                if (onlProposalForm.getOnlProposalFormIsd().getIsdname() != null) {
                  proposalStk.getStkInsured().setInsuredName(onlProposalForm.getOnlProposalFormIsd().getIsdname()); 

             //抛空指针异常的原因:proposalStk不为null,但是proposalStk.getStkInsured()为null,再去调用其他方法就会有异常。 StkInsured为对象,不是简单属性。{对象中嵌套对象}
                }

           }

       }    

    反射分为: 类反射、方法反射、属性反射。

    类反射: 通过反射创建类对象。

    方法反射:通过反射调用类中的方法信息。

    属性反射:通过反射获取类中的属性信息。

    一、类反射

    1、得到类Class对象。

    方式一: Class c1 = Student.class; //已知类名时使用此方法
    方式二: Class c2 = stu.getClass();//已知该类的对象时使用  
    方式三: Class c3 = Class.forName("com.demo.Student");//已知类的全路径名时使用此方法,会有一个ClassNotFoundException异常

    2、通过newInstance()方法创建对象的实例。

    ps: 注意调用 newInstance()方法创建对象时需要保证 Student类中有个无参数的构造方法!!!

    Class c=Class.forName("com.demo.Student");//这个为第一步中的方式三得到Class对象
    
    Student student = (Student)c.newInstance();//创建对象

     二、方法反射

    1、获取类中的所有方法

       public static void method_1() throws Exception {
          Class clazz = Class.forName("com.demo.Student");
    //获取的是该类中所有的公有方法,包含继承和实现的方法,不包含private私有方法。 Method[] methods = clazz.getMethods();
    //获取的是该类中的所有方法,包含私有方法,但不包含继承的方法。 methods = clazz.getDeclaredMethods();
    for(Method method : methods) { System.out.println(method); } }

    2、获取类中指定方法名的方法,并且运行该方法

        public static void method_2() throws Exception {
           Class clazz = Class.forName("com.demo.Student");
           //获取指定名称的方法; 参数: 方法名 show, 方法中的入参类型 int.class ,String.class
           Method method = clazz.getMethod("show", int.class,String.class);

    Object obj = clazz.newInstance(); method.invoke(obj, 18,"zhagnsan");//执行该方法; 参数: obj为当前类对象, 后面为运行该方法需要的参数值 }

    3、获取私有方法

            public static void method_3() throws Exception {
                 Class clazz = Class.forName("com.makaruina.reflect.Person");
                //想要获取私有方法必须用getDeclearMethod();
                 Method method = clazz.getDeclaredMethod("show", null); //当该私有方法时没有参数时使用null.
                 // 私有方法不能直接访问,因为权限不够。
                 method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。
            }

    三、属性反射

    public void isObjectFieldEmpty() throws Exception {
             
          Class clazz
    =Class.forName("com.demo.Student"); //得到类Class对象 Student student = clazz.newInstance(); Field[] fields = clazz.getDeclaredFields(); //得到所有属性集合 for(Field field : fields ){//遍历属性 field.setAccessible(true); //设置属性是可以访问的(私有的也可以) System.err.println(field.getName()+field.get(student)); // field.getName()得到属性名,field.get(student)得到属性名对应的属性值 } }

    应用示例:

       /**
         * 想用于对象嵌套对象时的非null判断,避免出现 空指针异常
         * 这里需要注意 序列化 以及带有默认值的字段 布尔类型 boolean 这两种类型是有值的
         * @throws Exception
         */
        @Test
        public void isObjectFieldEmpty() throws Exception {
              CheckboxVO checkVO = new CheckboxVO(); //创建被判断的对象
              checkVO.setCode("123");
              Class clazz=checkVO.getClass();  //得到类Class对象
              System.err.println("CheckVO的Class类对象:"+clazz);
              Field[] fs=clazz.getDeclaredFields(); //得到所有属性集合 
              System.err.println("Fields[]::"+fs);
              List<String> list=new ArrayList<String>();
              for(Field field:fs){            //遍历属性
                  field.setAccessible(true); //设置属性是可以访问的(私有的也可以)
                  System.err.println("Field::"+field);
                  System.err.println("field.get(checkVO):"+field.get(checkVO));
                 if(field.get(checkVO)==null||field.get(checkVO)==""){
                    String name=(String)field.getName();
                    list.add(name);
                 }
             }
              System.err.println("list:"+list);
            }

    CheckVO.java类

    package com.chinalife.proposal.web.build.basicplanVO;
    
    import java.io.Serializable;
    
    public class CheckboxVO implements Serializable{
        
        private static final long serialVersionUID = 1L;
    
        private String name;
    
        private boolean check;
    
        private String code;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public boolean isCheck() {
            return check;
        }
    
        public void setCheck(boolean check) {
            this.check = check;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
        
    }

    输出结果:

  • 相关阅读:
    注意力机制在CV领域的应用之SEnet
    知识蒸馏技术原理
    batchsize如何影响模型的性能
    docker网络 macvlan
    docker pull使用 代理
    auditd重启失败
    3.Golang的包导入
    2.golang应用目录结构和GOPATH概念
    使用git版本管理时的免密问题
    1.go语言目录结构
  • 原文地址:https://www.cnblogs.com/DFX339/p/9896476.html
Copyright © 2020-2023  润新知