Java_反射机制相关及其应用

Java的反射机制:是指允许程序员在程序运行的时候可以获取到某个类内部的信息(变量,方法,构造方法等),并且可以对其进行修改。

目录

一、通过反射机制获取Class类。

二、通过反射机制获取类的方法/属性/父类/接口

1、获取方法的方法:

2、获取属性的方法:

3、获取类的父类/接口

三、使用反射机制

1、通过反射机制了解泛型的本质

2、Spring中的使用

面试相关问题:项目中的反射机制的使用?


反射相关面试题

一、通过反射机制获取Class类。

Class类:JVM将class字节码文件加载到内存中,会将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个该类的Class类对象,作为方法区的访问入口。(类的加载机制

我们所定义的所有类,都是Class类的实例对象。那么Class的内部是什么样子呢。就可以使用java的反射机制获取Class类。

public class ReflectionDemo {
    public static void main(String[] args) {

        // 获取Class类对象的方式:通过类名
        Class c1 =  User.class;
        System.out.println(c1);

        // 获取Class类对象的方式:通过对象
        User user = new User();
        Class c2 = user.getClass();
        System.out.println(c2);

        // 获取Class类对象的方式
        try {
            Class c3 = Class.forName("reflection.User");//使用的是User类在项目中的完整路径
            System.out.println(c3);
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

二、通过反射机制获取类的方法/属性/父类/接口

public class ReflectionDemo2 {
    public static void main(String[] args) {
        User user = new User();
        printClassMethod(user);
    }


    public static void printClassMethod(Object object){
        //1、获取入参类的类型
        Class c = object.getClass();
        //2、获取入参类的名字
        String cName = c.getName();
        System.out.println("入参类的名字是:" + cName);
        //3、获取入参了类内部方法
        Method[] ms = c.getMethods();
        for(int i = 0; i < ms.length; i++){
            // 第一步,获取方法的返回值类型的类类型
            Class returnType = ms[i].getReturnType();
            System.out.println(returnType.getName() + " ");

            // 第二步,获取方法的名称
            String className = ms[i].getName();
            System.out.println(className + "(");

            // 第三步,获取方法参数类型
            Class[] paramTypes = ms[i].getParameterTypes();
            for(Class paramType : paramTypes){
                System.out.println(paramType + ",");
            }

            System.out.println(")");
        }
    }
}

1、获取方法的方法:

c.getMethods(); // 获取所有public的饿啊很熟,包括从父类继承来的
c.getMethod("getName"); // 返回方法名为getName的方法 
c.getDeclaredMethods(); // 获取该类所有自己声明的方法,不管什么访问权限 
c.getDeclaredMethod("getName");// 返回一个自己声明的且方法名为getName的方法

2、获取属性的方法:

c.getDeclaredFields();
c.getDeclaredField("name");
c.getField("name"); // 访问控制符必须是public

3、获取类的父类/接口

 c.getSuperclass();
 c.getInterfaces();

三、使用反射机制

1、通过反射机制了解泛型的本质

Java集合中的泛型是为了防止错误的输入,只在编译过程有效,只要绕过了编译,就无效了。

public class Reflection1 {

    public static void main(String[] args) {

        int number = 1;

        ArrayList<String> list1 = new ArrayList<>();
        ArrayList list2 = new ArrayList();
        // list1.add(number);
        list2.add(number);

        Class c1 = list1.getClass();
        Class c2 = list2.getClass();
        System.out.println(c1 == c2);

        try{
            Method m = c2.getMethod("add", Object.class);
            m.invoke(list1,number);
            System.out.println(list1);
        }catch (Exception e){
            System.out.println("异常了"+ e );
        }

    }
}

编译过程中,如果list1中增加了非String类型的数据,会报错,但是通过反射在运行期间对list1期间进行添加,则可以正常插入。

2、Spring中的使用

学习Spring的时候,我们知道Spring主要有AOP和IOC两大思想,它利用的就是反射机制。

对于Spring的核心AOP来说,使用了动态代理,其实底层也是反射。

面试相关问题:项目中的反射机制的使用

读取外部Excel文件,将文件中的字段赋值到具体类中,通过反射机制获取set方法并赋值。

 public static void generateModel(Object obj, String filedName, String value) throws Exception {
        // 获取这个类中和这个字段相关的信息
        Field field = obj.getClass().getDeclaredField(filedName);
        // 设置这个字段可以被赋值  默认不能赋值 
        field.setAccessible(true);
        transFieldValue( obj, field, value);
    }

    public static void transFieldValue(Object model, Field field, String value) throws Exception {
        // 获取字段名,将字段名的首字符大写,方便构造get,set方法
        String name = field.getName();
        name = name.substring(0, 1).toUpperCase() + name.substring(1);
        String type = field.getGenericType().toString();

        if (type.equals("class java.lang.String")) {
            Method m = model.getClass().getMethod("set"+name,String.class);
            if (StringUtil.isNotBlank(value.trim())) {
                m.invoke(model, value);
                return;
            }
        }else if (type.equals("class java.lang.Integer")) {
            Method m = model.getClass().getMethod("set"+name,Integer.class);
            if (StringUtil.isNotBlank(value.trim())) {
                m.invoke(model, Integer.parseInt(value));
                return;
            }
        }else if (type.equals("class java.lang.Short")) {
            Method m = model.getClass().getMethod("set"+name,Short.class);
            if (StringUtil.isNotBlank(value.trim())) {
                m.invoke(model, Short.parseShort(value));
                return;
            }
        }else if (type.equals("class java.lang.Double")) {
            Method m = model.getClass().getMethod("set"+name,Double.class);
            if (StringUtil.isNotBlank(value.trim())) {
                m.invoke(model, Double.parseDouble(value));
                return;
            }
        }else if (type.equals("class java.math.BigDecimal")) {
            Method m = model.getClass().getMethod("set"+name,BigDecimal.class);
            if (StringUtil.isNotBlank(value.trim())) {
                m.invoke(model, new BigDecimal(value));
                return;
            }
        }else if (type.equals("class java.lang.Boolean")) {
            Method m = model.getClass().getMethod("set"+name,Boolean.class);
            if (StringUtil.isNotBlank(value.trim())) {
                m.invoke(model, Boolean.parseBoolean(value));
                return;
            }
        }else if (type.equals("class java.util.Date")) {
            Method m = model.getClass().getMethod("set"+name,Date.class);
            if (StringUtil.isNotBlank(value.trim())) {
                SimpleDateFormat sdf_long = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                SimpleDateFormat sdf_short = new SimpleDateFormat("yyyy-MM-dd");
                Date date;
                if (value.length() > 10){
                    date = sdf_long.parse(value);
                }else {
                    date = sdf_short.parse(value);
                }
                m.invoke(model, date);
                return;
            }
        }
    }

参考文章

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值