浅谈java反射【原创】

参考书籍《疯狂java》

反射的用处

反射能获取对象的属性,以及对象的属性值,甚至是私有的方法,这个一般是用在框架的,或者是权限校验,参数校验等框架的设计,反射在面试也比较常见,但是在实际的项目中,每个开发者接触的机会不多,一般都是大牛们在负责写这些,利用反射写一些通用组件等等,来解决发杂需求或者给其他开发者提供组件

提问

如何通过反射获取UpdateCheckRequestType中子对象list里面的inspectionItemId以及checkDTO中的description

public class UpdateCheckRequestType  {
    private CheckDTO checkDTO;
    private List<InspectionDTO> list;
}

public class CheckDTO {
    private String id;
    private String description;

public class InspectionDTO {
    private String inspectionItemId;
    private String inspectionValue;

首先要明确一点,在反射获取属性的过程中一定是先有class,然后才有属性,不多说上代码

 public static void main(String[] args) {
        // 准备数据
        CheckDTO dto = new CheckDTO();
        dto.setDescription("123434");
        InspectionDTO inspectionDTO = new InspectionDTO();
        inspectionDTO.setInspectionItemId("123234");
        List<InspectionDTO> list = new ArrayList<>();
        list.add(inspectionDTO);
        UpdateCheckRequestType type = new UpdateCheckRequestType();
        type.setList(list);
        type.setCheckDTO(dto);
    }

有些伙伴会问,直接new UpdateCheckRequestType不就完事了吗?为啥还要给里面的子对象赋值?你如果直接new出来,没有赋值,拿到的子对象就是null,通过这个子对象去获取子对象里面的属性是获取不到的,会抛出空指针异常,还是那句话,现有class再有属性,既然class都是null,那么何来的属性呢?

  // 获取type的属性
        Field[] fields = type.getClass().getDeclaredFields();
        System.out.println(fields[0].getName());
输出结果
checkDTO
  1. 这里要说下的是getDeclaredFields,getDeclaredField,getFields,getField
    首先不包含s的获取的是单个属性的,需要提前知道属性的名字,而且当不存在时候会有异常抛出
  2. 不含有Declared的方法只能获取共有属性,而Declared可以获取私有的属性,我们实体类中的属性都是私有,当然还有getMethod等等规则和上面是一样的
    从这里看到我们已经拿到了type中的子对象checkDTO,对type来说checkDTO是其中的一个属性,因此我们这里可以直接或取checkDTO,下面获取checkDTO中的Description的值
   // 获取type的属性
        Field[] fields = type.getClass().getDeclaredFields();
        // 设置私有属性可以访问
        fields[0].setAccessible(true);
        // 获取checkDTO的实际对象
        Object value = fields[0].get(type);
        System.out.println(value.toString());

如果缺少设置私有属性允许访问这一步会抛出如下异常
Exception in thread "main" java.lang.IllegalAccessException: Class com.lightkits.mes.dto.equipment.FanShe can not access a member of class com.lightkits.mes.dto.equipment.UpdateCheckRequestType with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
    at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
    at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
    at java.lang.reflect.Field.get(Field.java:390)
    at com.lightkits.mes.dto.equipment.FanShe.main(FanShe.java:28)

输出结果如下
CheckDTO(id=null, description=123434, equipmentId=null, remark=null, collector=null, taskStatus=null, taskNum=null)

OK,离目标又进了一步,接下来反射获取description

   Field[] fields1 = value.getClass().getDeclaredFields();
        System.out.println(fields1[1].getName());
输出结果
description
接下来获取description的值 套路是一样的
 // 获取checkDTO的实际对象
        Object value = fields[0].get(type);
        System.out.println(value.toString());
        Field[] fields1 = value.getClass().getDeclaredFields();
        System.out.println(fields1[1].getName());
        fields1[1].setAccessible(true);
        System.out.println(fields1[1].get(value));
值得注意的是在获取子对象的属性值的时候get里面放置的是子对象
输出结果
123434

ok 既然有get 那就必定有set

Object value = fields[0].get(type);
        System.out.println(value.toString());
        Field[] fields1 = value.getClass().getDeclaredFields();
        System.out.println(fields1[1].getName());
        fields1[1].setAccessible(true);
        System.out.println(fields1[1].get(value));
        fields1[1].set(value, "你好");
        System.out.println(fields1[1].get(value));
输出结果对比
123434
你好

set可以用来改变属性值,这个在sqlhelp这个框架里面用到了,有兴趣的可以去了解下,总之来说get和set在反射中使用频率比较高
如果想获取list对象里面属性对象的属性值这个就和上面的套路是一样的了,直接上代码

  // 获取type的属性
        Field[] fields = type.getClass().getDeclaredFields();
        // 设置私有属性可以访问
        fields[1].setAccessible(true);
        // 在强转之前需要事先预判,否则会抛出异常
        List<?> list1 = (List<?>)fields[1].get(type);
        Object o = list1.get(0);
        Field[] fields1 = o.getClass().getDeclaredFields();

这里是拿到子对象的属性,能拿到属性,就可以解决其他问题,套路和上面是一样
在项目中的多数情况下是要去拿属性上的注解,根据属性注解去做操作,使用的方法是

  Field[] fields1 = o.getClass().getDeclaredFields();
        Annotation[] annotations = fields[0].getAnnotations();
        System.out.println(annotations.length);
        System.out.println(annotations[0].annotationType());
结果如下
1
interface javax.validation.Valid

总结:反射面试中经常问,java的底层也依赖,比较重要,进行反射切记先有class才有属性,如果class是null那就啥都没得

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容

  • 1. 了解 Java 中的反射 1.1 什么是 Java 的反射 Java 反射是可以让我们在运行时获取类的函数、...
    Ten_Minutes阅读 537评论 0 4
  • 课程地址:Java基础之 — 反射(非常重要) (使用的前提条件:必须先得到代表的字节码的Class,Cla...
    叨唧唧的阅读 686评论 0 2
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,100评论 1 32
  • (转自csdn) 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示...
    尼尔君阅读 227评论 0 1
  • 我喜欢 夕阳中的枝柳 似隐似现似幕影 丝丝缕缕不回头 清冷中透着多情 在心中撩起一帘幽梦 我喜欢 夕阳中的小路 寒...
    月牙儿弯阅读 179评论 0 2