Java反射之初体验

一、什么是反射?

在运行状态中,对于任意一个类,都能获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取信息以及动态调用对象的方法的功能就称为Java的反射机制。简单来讲,通过反射,该类对我们来说就是完全透明的,想要获取任何东西都可以。

想要使用反射机制,就必须要先获取到该类的字节码对象(.class),通过字节码对象文件,就能够通过该类中的方法获取到我们想要的信息(方法、属性、类名、父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

1、获取字节码对象的3种方式

(1) 通过Class类中的静态方法forName()直接获取到一个类的字节码文件对象

 例: Class<?> aClass = Class.forName("com.example.homework.model.entity.Person");

 即可获取到Person类的字节码对象

(2)通过类自身获取

Class<Person> p2Class = Person.class;

(3)通过类的实例获取

Person person = new Person();
Class<? extends Person> p3Class = person.getClass();

二、通过反射获取我们需要的信息

通过字节码对象创建实例

通过反射获取实例对象,直接使用字节码对象newInstance()即可创建一个实例

Class<Person> p2Class = Person.class;

Person p2 = p2Class.newInstance();

通过反射获取属性

获取所有属性,不包含私有属性:   Field[] fields = p2Class.getFields();

获取特定属性,不包含私有属性:   Field pai = p2Class.getField("pai");

如果需要获取私有属性需要使用下面的api

Field[] declaredFields = p2Class.getDeclaredFields();

Field idField = p2Class.getDeclaredField("id");

获取方法:

我们首先列出Person类中的两个测试方法:

//  公有方法
    public String test1(){
        System.out.println("test1,已经执行了!");
        return "hello world!";
    }
//    私有方法
    private String privateTest2(String name,Double d){
        System.out.println(name+"你好;工资:"+d);
        return "hello"+name;
    }

获取类的方法(不包含私有方法)并调用:

Method m1 = p2Class.getMethod("test1");

m1.invoke(p2);

这里为一个无参的方法,调用时无需指定参数类型,如果是有参方法,需要明确指定参数类型

获取类的私有方法,且该方法有参数:

 Method privateTest2 = p2Class.getDeclaredMethod("privateTest2", String.class, Double.class);
 privateTest2.setAccessible(true);
 privateTest2.invoke(p2,"alice",900.85);

result:
 alice你好;工资:900.85  

三、应用

 springdata jpa 中构造自定义转换类的时候,通过SQL查询出来的别名可以和我们的实体类对应,并在transformTuple中构建实体对象,该实体对象的属性即为SQL查询出来的字段,数值是统计出来的结果,

public class DefineResultTransformer<T> implements ResultTransformer, Serializable {
    private static final long serialVersionUID = 775781526148172513L;

    private Class<T> resultClazz;
    private BeanUtilsBean beanUtilsBean;

    public DefineResultTransformer(Class<T>  resultClass){
        this.resultClazz = resultClass;
        this.beanUtilsBean = BeanUtilsBean.getInstance();
    }

    @Override
    public Object transformTuple(Object[] tuple, String[] aliases) {
        Object result = null;

        Field[] fields = resultClazz.getDeclaredFields();
        try {
            result = resultClazz.newInstance();
            for(int i =0 ;i<aliases.length; i++){
                for(Field field : fields){
//   1、忽略大小写映射,如SQL查询字段为 "username" 可直接映射为Java实体类中userName属性
//   2、去掉"_" 映射,如SQL查询出的字段为 "user_name" 也可直接映射为Java实体类中userName属性
                    if(field.getName().equalsIgnoreCase(aliases[i].replaceAll("_",""))){
                        beanUtilsBean.setProperty(result,field.getName(),tuple[i]);
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public List transformList(List collection) {
        return collection;
    }
    
}

该工具转换类,接收一个结果类的字节码对象,然后通过反射获取该对象的属性,并和SQL查询查来的别名以及结果封装数据构造对象,最终完成SQL查询结果到Java对象的转换。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值