• 今天由于业务需要,看一段数据库中的表转化成用户可以看懂的数据,也就是把一些字段比如Date用ms存的,转化为'yyyy-MM-dd'这种格式,但是由于字段太多,所以利用Java反射机制自带的BeanUtils相关的方法来进行转化(要求两个类的属性名称相同),当然这个方法只支持基本数据类型,如Long,Integer,String,Short之类的转化,但是像Date类型就需要自己手动判断来转,这就出现了今天所遇到的坑

  • 先看下反射机制是如何获取类的方法的:

    Class clazz = object.getClass();
    clazz.getDeclaredFields();
    clazz.getFields()

    ​ 通过getClass()方法来获取类的定义信息,通过定义信息再调用getFields()方法来获取类的所有公共属性,或者调用getDeclaredFields()方法来获取类的所有属性,包括公共,保护,私有,默认的方法,但是这里有一点要注意的是这个方法只能获取当前类里面显示定义的属性,不能获取到父类或者父类的父类及更高层次的属性的,所以我们要想获取类的所有属性,还要获取父类的属性:

    public static Field[] getAllFields(Object object){
    Class clazz = object.getClass();
    List<Field> fieldList = new ArrayList<>();
    while (clazz != null){
    fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
    clazz = clazz.getSuperclass();
    }
    Field[] fields = new Field[fieldList.size()];
    fieldList.toArray(fields);
    return fields;
    }

    ​ 这个方法通过while循环及getSuperClass()方法获取当前类的父类再进行getDeclaredFields()即可,注意这个方法返回的是一个Field数组,然后如果我们想要把这些属性拼接到一起,当然是使用链表更方便一些,利用Arrays.asList()方法将数组转化为链表,注意:这个方法返回的是一个List<>也就是抽象列表,所以要将其再用ArrayList初始化一次得到的列表才可变,否则得到的是一个不可变的列表.

    ​ 然后我们再利用列表的toArray()方法将列表转为数组,注意:这里又有一个坑,这个方法提供了两种实现:

    Object[] toArray();
    <T> T[] toArray(T[] a);

    ​ 第一种无参,但注意,返回值类型为Object数组类型,直接这么写肯定会报错,但是如果强制转换为需要的类型,则在运行时会抛这样一个异常:

     
    异常信息

    ​ 程序会告诉你无法这么转换,所以这里要注意

    ​ 第二种的参数就填你要转换的数组就可以,但是他要求数组的长度是等于链表的长度的,否则会编译不通过,所以得到链表之后在初始化数组即可

  • 然后这里在测试时导师提到了一个点就是循环依赖的问题,担心while会跳不出来,但是这里其实跟属性的具体类型是无关的,所以不会出现这个问题,但是就顺便了解了下循环依赖的相关概念,比如我定义两个类:

    class ClassA {
    int a;
    ClassB ab;
    public ClassA(){
    ab = new ClassB();
    }
    }
    class ClassB extends ClassA {
    int b;
    ClassA ba; public ClassB() {
    this.ba = new ClassA();
    }

    乍一眼看上去有很大问题嘛,怎么A是B的父类,A里面还有一个属性是B类的,其实这个问题跟继承关系也不大,只不过继承关系会让人印象更深刻,因为这段代码编译是可以通过的,那么我们来实例化一个B类看看会发生什么:

     
    异常信息

    接下来基本都是这样的情况了,java抛出了栈溢出,从结果中也可以想出这个问题,即A的属性引用了B类,而B的属性又引用了A类,这使得在B类实例化时去初始化A,A又初始化B,就这么陷入了一个死循环,最终导致程序栈溢出,所以我们在实际编码过程中要千万注意这种情形,如果发生在业务中,则是巨大的隐患存在.

作者:xdlkc
链接:https://www.jianshu.com/p/6fe3e0e185ac
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Java 获取对象全部属性 包括 父类属性的更多相关文章

  1. 【java】java获取对象属性类型、属性名称、属性值

    java获取对象属性类型.属性名称.属性值 获取属性 修饰符:[在Field[]循环中使用] String modifier = Modifier.toString(fields[i].getModi ...

  2. java获取对象属性类型、属性名称、属性值

    /** * 根据属性名获取属性值 * */ private Object getFieldValueByName(String fieldName, Object o) { try { String ...

  3. java获取对象属性类型、属性名称、属性值 【转】

    /** * 根据属性名获取属性值 * */ private Object getFieldValueByName(String fieldName, Object o) { try { String ...

  4. java 获取对象的数据类型

    // java 获取对象的数据类型 public static String getType(Object object){ String typeName=object.getClass().get ...

  5. Java获取项目根目录等其他系统属性

    一 相对路径的获得 说明:相对路径(即不写明时候到底相对谁)均可通过以下方式获得(不论是一般的java项目还是web项目) String relativelyPath=System.getProper ...

  6. Java-Reflection反射-获取包括父类在内的所有字段

    前言 今天Android移动端要加个新功能,所以回归Android程序员的身份.开发的过程中,发现了之前的代码写的有很多问题,真的应该把时间抽出来重构一下了. 其中有反射的一个坑,工具类某方法反射获取 ...

  7. Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别

    Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别 ​ 在工作中遇到一个问题,就是你需要去判断某个字符串是不是对象的某个成员属性名,然后根据判断结果 ...

  8. 乐字节Java反射之二:实例化对象、接口与父类、修饰符和属性

    大家好,小乐继续接着上集:乐字节Java反射之一:反射概念与获取反射源头Class 这次是之二:实例化对象.接口与父类.修饰符和属性 一:实例化对象 之前我们讲解过创建对象的方式,有new .克隆.反 ...

  9. Java反射获取对象VO的属性值(通过Getter方法)

    有时候,需要动态获取对象的属性值. 比如,给你一个List,要你遍历这个List的对象的属性,而这个List里的对象并不固定.比如,这次User,下次可能是Company. e.g. 这次我需要做一个 ...

随机推荐

  1. NLP之概率图模型

    1.概率图模型 概率图模型是一类用图来表达变量相关关系的概率模型,它以图为表示工具,最常见的是用一个结点表示一个或一组随机变量,结点之间的边表示变量间的概率相关关系.概率图模型可大致分为两类:第一类是 ...

  2. 8.11 NOIP模拟测试17 入阵曲+将军令+星空

    T1 入阵曲 前缀和维护可以得60分 f[x1][y1][x2][y2]=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];  O(n4) ...

  3. rIoTboard学习系列

    刚在咸鱼买了块开发板,比较老了14年的,SOC为imx6solo,内核3.10,uboot2009的,准备先移植一个较新的uboot 到nxp的git下获取他们维护的uboot,网址http://gi ...

  4. Windows10 WSL下 龙芯3A 交叉编译环境搭建

    记个流水账避免事后忘记怎么搭建的 - - 环境 Key Value 系统 Windows10 WSL系统 Ubuntu 下载工具链 http://www.loongnix.org/index.php/ ...

  5. mac os 使用 from scipy.misc import imread ImportError: cannot import name 'imread'

    mac os 使用 from scipy.misc import imread ImportError: cannot import name 'imread' 问题1: 我原先安装了 pillow ...

  6. vertica ROS和WOS错误

    频繁写入vertica,可能导致ROS和WOS错误.如下: java.sql.SQLTransientException: [Vertica][VJDBC](5065) ERROR: Too many ...

  7. ThinkPHP连接Oracle数据库的详细教程

    一. 操作环境搭建 系统:Windows7 旗舰版 64位PHP环境:wampserver2.2e-php5.4.3-httpd2.2.22-mysql5.5.24 32位版ThinkPHP:3.0正 ...

  8. SQL -------- 简单的增删改查

    sql  结构化查询语言,一种ansi 的标准计算机语言,为了访问数据库 可以做什么:可以对数据库 和表进行创建于删除, 对表里面的数据进行增删改查. 也可以创建存储过程和视图,对表设置权限 RDBM ...

  9. 四种软件开发模式:tdd、bdd、atdd和ddd的概念

    看一些文章会看到TDD开发模式,搜索后发现有主流四种软件开发模式,这里对它们的概念做下笔记. TDD:测试驱动开发(Test-Driven Development) 测试驱动开发是敏捷开发中的一项核心 ...

  10. RDD的转换操作,分三种:单value,双value交互,(k,v)对

    import org.apache.spark.rdd.RDDimport org.apache.spark.{Partitioner, SparkConf, SparkContext} object ...