文档章节

java框架的核心:反射机制详解

tongqu
 tongqu
发布于 2015/03/11 23:01
字数 1405
阅读 527
收藏 67

假设我们有一个Master类,下面我开始对该类进行反射机制的研究:

class Master{
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Master(String name,int age){
        this.name=name;
        this.age=age;
    }
    public Master(){
        
    }
}

    下面我来写一个ObjectUtil类,该类的私有变量和构造函数如下

    private Map<String, Class> map=null;//用来存放待处理类中存在的属性以及属性类型
    private static Object object;//我们要处理的类
    public ObjectUtil(Object object){
        this.object=object;
    }

一. Field类

Field在jdk中的描述:提供有关类或接口的单个字段的信息,可以对它的动态访问权限。因此,我们可以根据field对象得到object中的属性名,属性类型和方法等信息。

    /*
     * 获取object的属性名
     * */
     public  Map<String, Class> getNames(){
        Field fields[]=object.getClass().getDeclaredFields();
        map=new HashMap<String, Class>();
        for (int i = 0; i < fields.length; i++) {
            map.put(fields[i].getName(), fields[i].getType());
        }
        return map;
    }

上面代码展示了如何通过Field获取对象中的属性名和该属性的类型,对应的方法分别是 field.getName()和field.getType()。

        除了获取name和type,field类还有许多其他的方法,比如.getGenericType()返回的是getType()的string类型,

toGenericString()返回的是该字段笼统的概括 如:private java.lang.String com.text.Dog.name

getModifiers()返回的是该属性的范围的int值:public<==>1,private<==>2

set(object,objectVal)该方法的用途比较有限,要求属性是public类型的属性才能用,但大部分对象类是不会把属性设置成public的。它的第一个参数是类中的某个属性,第二个参数是该属性的值,相当于在类中中直接定义其他类的属性值:

Master master=new Master();
         master.id=12;

 二.  Method类

    下面我们通过class类获取对象属性的值,由于对象属性一般都是私有的,想获取属性的值必须执行get属性方法,所以我们需要通过构造get方法名来获得值

/*
     * 根据object的属性名某对象该属性的属性值
     * */
    public  Object getValue(String name){
        if(map==null){
            this.getNames();
        }
        String methodName="get"+name.substring(0,1).toUpperCase()+name.substring(1,name.length());
        Method method;
        Class class1=map.get(name);
        Object valObject=null;
        try {
            method=object.getClass().getDeclaredMethod(methodName, new Class[]{});
            valObject=method.invoke(object,new Object[]{});
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
         return valObject;
    }

    从上述代码中可以看出,

object.getClass().getMethod(methodName, new Class[]{});

    可以构造出一个方法实例,方法名是methodName,方法中传入的参数类型是new Class[]{}


valObject=method.invoke(object,new Object[]{});

    可以获取object对象在执行该方法的时候返回的对象,new object[]{}是对应参数,数量必须与上面的new class的数量相同不然报错,如果该方法是void方法,则返回null。

    如果我们想让该方法返回string类型的值,只需把valObject强转为string即可,其它类型也相仿。


valObject=class1.newInstance();

    该方法需要注意的是,假设我们要获取的属性真的是一个自定义的对象(比如在master中定义了一个dog类),这个对象的构造函数中不能有参数,这就是spring框架规定如果bean中非要写一个带参数的构造函数的话,必须重写一遍不带参数的构造函数 的原因。  

    get方法完成,我们来写最难的set方法:

/*
     * set方法
     * */
    public  ObjectUtil setValue(String name,Object valueObject){
        String setMethod="set"+name.substring(0,1).toUpperCase()+name.substring(1,name.length());
        if(map==null){
            map=this.getNames();
        }
        Class class1=map.get(name);
        Method method;
        try {
            method=object.getClass().getDeclaredMethod(setMethod, class1);
            method.invoke(object, valueObject);
            
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return new ObjectUtil(object);
    }

这里返回ObjectUtil的原因应该很容易理解了,这样就可以链式set值了,比如

        ObjectUtil util=new ObjectUtil(new Master("xiaoli", 13));
         util.setValue("age", 1).setValue("name", "xxx");

自此set、get方法完成,全部代码总结如下

package com.text;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.KeyStore.Entry;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ObjectUtil {
    private Map<String, Class> map=null;
    private static Object object;
    public ObjectUtil(Object object){
        this.object=object;
    }
    public static void main(String[] args) {
         ObjectUtil util=new ObjectUtil(new Master("xiaoli", 13));
         util.setValue("age", 1).setValue("name", "xxx");
         
    }
    /*
     * 获取object的属性名
     * */
     public  Map<String, Class> getNames(){
        Field fields[]=object.getClass().getDeclaredFields();
        map=new HashMap<String, Class>();
        for (int i = 0; i < fields.length; i++) {
            map.put(fields[i].getName(), fields[i].getType());
        }
        return map;
    }
    /*
     * 根据object的属性名某对象该属性的属性值
     * */
    public  Object getValue(String name){
        if(map==null){
            this.getNames();
        }
        String methodName="get"+name.substring(0,1).toUpperCase()+name.substring(1,name.length());
        Method method;
        Class class1=map.get(name);
        Object valObject=null;
        try {
            method=object.getClass().getDeclaredMethod(methodName, new Class[]{});
            valObject=method.invoke(object,new Object[]{});
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
         return valObject;
    }
    /*
     * set方法
     * */
    public  ObjectUtil setValue(String name,Object valueObject){
        String setMethod="set"+name.substring(0,1).toUpperCase()+name.substring(1,name.length());
        if(map==null){
            map=this.getNames();
        }
        Class class1=map.get(name);
        Method method;
        try {
            method=object.getClass().getDeclaredMethod(setMethod, class1);
            method.invoke(object, valueObject);
            
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return new ObjectUtil(object);
    }
}
class Dog{
    private String name;
    private int id;
    private Master master;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Dog(String name,int id,Master master){
        this.name=name;
        this.id=id;
        this.master=master;
    }
    public Dog(){
        System.out.println("被执行");
    }
    public Master getMaster() {
        return master;
    }
    public void setMaster(Master master) {
        this.master = master;
    }
}
class Master{
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Master(String name,int age){
        this.name=name;
        this.age=age;
    }
    public Master(){
        
    }
}

















© 著作权归作者所有

tongqu
粉丝 38
博文 37
码字总数 26162
作品 0
海淀
私信 提问
一份关于 Java、Kotlin 与 Android 的学习笔记

JavaKotlinAndroidLearn 这是一份关于 Java 、Kotlin 、Android 的学习笔记,既包含对基础知识点的介绍,也包含对一些重要知识点的源码解析,笔记的大纲如下所示: Java 重拾Java(0)-基础知...

叶应是叶
2018/08/08
0
0
【免费】全网独家:详解Java反射机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/silencezwm/article/details/85115991 【免费】全网独家:这是一份非常值得珍藏的Android知识体系!!! 本文...

silencezwm
2018/12/20
0
0
Android 4.4(KK)中利用APP打开关闭数据流量

在Android 4.4中,在app中打开或关闭数据流量 如果有这方面需求可以参考。 思路 利用JAVA的反射机制(Reflection),来调用CONNECTIVITY_SERVICE完成相关操作。 关于JAVA的反射机制,可以参考...

W_X
2014/12/17
0
4
Java程序员进化为架构师需要掌握的知识

Java程序员进化为架构师掌握的知识: 一:Java知识 1、进制转换 2、Java基本数据类型 面向对象相关知识 3、类、接口、抽象类 this关键字、static关键字、final关键字 方法的参数传递机制 Ja...

andogo
2014/05/16
1K
2
平日看到的JAVA相关技术链接

开源技术框架类: menagerie (ZooKeeper-based Java Concurrency Libraries) https://github.com/openUtility/menagerie#readme fastjson (Fast是一个JSON的Processor,功能强大、易用、快速......

qingtian
2011/02/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Redux

Redux概念 Redux = Reducer + Flux,数据层框架,将所有数据都存储到store中 Redux的工作流程 Antd的使用 安装npm install antd --save import 'antd/dist/antd.css'import { Input, Butto......

星闪海洋
今天
4
0
OSChina 周一乱弹 —— 你们谁看见了我的诺贝尔奖

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @脚板薯 :这么晚不睡只为找到一首歌,晚安。 ♫Say You Want Me♪ ♫Say You Want Me♪ - Augustana 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
436
17
我为什么要写微信公众号

埋一颗种子,细心呵护,静待她枝繁叶茂,葱郁参天 V2论坛上有个帖子【做程序员最重要的还是一定要有自己的作品】,作者写道: 能有一个作品和你的名字联系在一起,应当成为在职业生涯前期着意...

运维咖啡吧
今天
3
0
数据库

数据库架构 数据库架构可以分为存储文件系统和程序实例两大块,而程序实例根据不同的功能又可以分为如下小模块。 1550644570798 索引模块 常见的问题有: 为什么要使用索引 什么样的信息能成...

一只小青蛙
今天
5
0
PHP常用经典算法实现

<? //-------------------- // 基本数据结构算法 //-------------------- //二分查找(数组里查找某个元素) function bin_sch($array, $low, $high, $k){ if ( $low <= $high){ $mid = int......

半缘修道半缘君丶
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部