java反射总结

反射

文章的结构分布(自己的知识体系总结)
在这里插入图片描述

一.了解java的反射机制

   百度百科:
   Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。 

java中关于反射 的类都在java.lang.reflect包
1.java中的一个类有若干个对象组成,field属性对象,method方法对象,constructor构造器对象,Modifier修饰符对象,Void对象
2.反射是类的自省,通过反射可以动态获取类中的方法 构造方法,属性等类的内容
3.我们以前编写的代码,是编译期代码,是硬编码,反射在运行期执行的代码,使用反射编写的代码并没有具体定义那个对象,它会根据需要在运行期自动创建类的对象并调用相关的方法
4.我们可以通过反射来开发通用功能的方法或者类;目前所使用的所有企业级开发框架都离不开反射

总结:
反射就是一个技术,通过获得字节码对象,在运行期执行相关的操作,如获得自身的属性,方法,构造器,也可以根据需要(根据编写的代码)创建自身的对象!
问题1:
反射为什么可以写出通用的功能?
因为可以通过Class cla ,也就是通过泛型和字节码,可以使得出传入任何对象的字节码,然后通过反射创建其对象,并进行了一系列操作

问题2:
Java中同一个类创建的俩个对象字节码一样吗?
不一样

二.java反射的基本使用:
1.Class类:
Class类在java,lang>Class类,该类就是用于表示类或者接口的字节码对象
获取一个类的Class对象有以下3中方式
(1)完整路径名: Class.forName

        Class aClass = Class.forName("com.fan.model.User");
        System.out.println(aClass);

(2)通过类名.Class直接获得

        Class<User> userClass = User.class;
        System.out.println(userClass);

(3)通过对象名,getClass()获得
代码如下:

        User user = new User();
        Class<? extends User> Class = user.getClass();
        System.out.println(Class);

2.使用反射操作类中的属性
方法介绍:
getField(String fieldName) 通过属性名获得一个属性对象
getFields() 获得本类以及父类的public属性,返回一个数组
getDeclaredField(String name)通过属性名指定的一个属性对象
getDeclaredFields() 获取本类中所有的属性,返回一个数组
getName() 获取属性的属性名,返回String
getType() 获取属性的类型名,返回Class
getModifiers() 获取属性的修饰符,返回数字
field.set(obj,“fjg”) 给属性赋值,第一个参数是属性所属的对象,第二个参数是属性的值,调用set给属性赋值,属性不能是private,protected,默认,只有public才可以
field.get(obj)获得属性,返回Object

package com.fan.reflect;

import com.fan.model.User;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class 通过反射操作类中的属性 {
    public static void main(String[] args) {
        Class<User> userClass = User.class;
        //获得类中所有的属性
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            //属性名
            String name = declaredField.getName();
            //类型名
            Class type = declaredField.getType();
            //修饰符
            int modifiers = declaredField.getModifiers();
            String s = Modifier.toString(modifiers);
            System.out.println("属性名:"+name);
            System.out.println("类型名:"+type);
            System.out.println("修饰符:"+s);
            System.out.println(s+""  +type+" "+name);
        }
    }
}



package com.fan.reflect;

import com.fan.model.User;
import java.lang.reflect.Field;

public class 根据属性名获得属性对象并调用该属性 {
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        //根据属性名获得一个属性对象
        Field field = userClass.getDeclaredField("user_name");
        /*
        * 调用属性
        *编译期调用属性的方法:
        * User  user=new  User();
        * user.user_name="樊军刚";
        * 反射调用属性
        *1.设置属性的值
        * field.set(obj,"樊军刚")
        * 参数1:对象,属性所属的对象
        * 参数2:属性的值
        * 2.获得属性的值
        * Object  val=field.get(obj);
        * //获取属性的值
        */
        //通过Class创建类的对象,该方法调用类的无参数的构造方法创建类的实例
        User user = userClass.newInstance();
        field.set(user,"樊军刚");//设置属性的值
        String val= (String) field.get(user);
        System.out.println(val);


    }
}


3.操作类中的方法
方法:
getMethod(String fieldName,Class<?> …parametertypes) 通过方法名和参数类型获得一个方法对象
getMethods() 获得本类以及父类的public方法,返回一个数组
getDeclaredMethod(String name,Class<?> …parametertypes)通过方法名指定的一个方法对象
getDeclaredMethods() 获取本类中所有的方法对象,返回一个数组
getName() 获取方法的方法名,返回String
getModifiers() 获取方法的修饰符,返回数字
getReturnType()获取方法的返回类型
getParameterTypes()获取方法中参数的类型,返回数组
getExpectionTypes()获取方法抛出的异常,返回数组
方法体无权获得
invoke(obj,“值”) 调用方法,第一个是方法的所属对象,后面的是要传入的值

package com.fan.reflect;

import com.fan.model.User;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class 通过反射操作类中的方法 {
    public static void main(String[] args) {
        Class<User> userClass = User.class;
        //获得类中所有的方法,获得当前类的所有方法对象,每个方法都是一个Method对象
        Method[] declaredMethods = userClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            //方法名
            String name = declaredMethod.getName();
            //方法的返回类型
            Class returnType = declaredMethod.getReturnType();
            //方法的修饰符
            int modifiers = declaredMethod.getModifiers();
            String s = Modifier.toString(modifiers);
            //方法的参数列表,返回方法中参数类型的数组
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            //方法抛出异常
            Class<?>[] exceptionTypes = declaredMethod.getExceptionTypes();
            //方法体无权获得
            System.out.println("方法名"+name);
            System.out.println("方法的返回类型:"+returnType);
            System.out.println("方法的参数列表");
            for (Class<?> parameterType : parameterTypes) {
                System.out.println(parameterType);
            }
            System.out.println("异常:");
            for (Class<?> exceptionType : exceptionTypes) {
                System.out.println(exceptionType);
            }
            System.out.println("----------------------------------");
        }
    }
}



package com.fan.reflect;

import com.fan.model.User;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class 获得某个方法并调用某个方法 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<User> userClass = User.class;
        //获得一个方法对象,根据方法名和参数列表(参数类型)来确定一个唯一额的方法
        Method method = userClass.getDeclaredMethod("setUser_name", String.class);
        /**
         * 调用方法
         * 编译期调用方法:
         * User user=new  User();
         * user.setUser_id=12;
         * 反射中调用方法:
         * 参数1:对象,值那个对象的方法
         * 参数2:方法参数的值
         *返回值为方法的返回值
         * Object   returnValue=method.invoke(obj,12);
         * System.out.println(returnValue);
         * 调用getUser_id()方法获得属性的值
         * Method  method1=cla.getDeclareMethod("getUser_id")
         * 调用方法
         *Object  val=method1.invoke(obj)
         */
        //创建类的实例
        User user = userClass.newInstance();
        Object returnValue= method.invoke(user, "fjg");
        //调用getUser_id()方法获得属性的值
        Method method1 = userClass.getDeclaredMethod("getUser_name");
        Object value = method1.invoke(user);
        System.out.println(value);


    }
}


4.操作类中的构造器
方法:
getConstructor(Class<?> …parametertypes) 通过参数类型获得一个构造器对象
getConstructors() 获得本类的public构造器方法,返回一个数组
getDeclaredConstructor(Class<?> …parametertypes)通过参数类型获得指定的一个构造器对象
getDeclaredConstructors() 获取本类中所有的构造器对象,返回一个数组
getName() 获取构造器的构造名,返回String
getModifiers() 获取构造器的修饰符,返回数字
getParameterTypes()获取构造器中参数的类型,返回数组
getExpectionTypes()获取构造器中抛出的异常,返回数组
newInstance() 创建对象,如果其有值,那么就相当于给对象赋值
代码:

package com.fan.reflect;

import com.fan.model.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class 通过反射操作类中的构造方法 {
    public static void main(String[] args) throws NoSuchMethodException {
        Class<User> userClass = User.class;
        //获得类中所有的构造方法
        Constructor<User> constructor1 = userClass.getConstructor();
        Constructor[] constructors = userClass.getDeclaredConstructors();
        //遍历构造方法
        for (Constructor constructor : constructors) {
            //方法名
            String name = constructor.getName();
            //方法的修饰符
            String modifierStr = Modifier.toString(constructor.getModifiers());
            //方法的参数列表
            Class[] parameterTypes = constructor.getParameterTypes();
            //方法抛出的异常
            Class[] exceptionTypes = constructor.getExceptionTypes();
            System.out.println("方法名:"+name);
            System.out.println("方法的修饰符:"+modifierStr);
            System.out.println("参数列表:");
            for (Class parameterType : parameterTypes) {
                System.out.println(parameterType);
            }
            System.out.println("异常:");
            for (Class exceptionType : exceptionTypes) {
                System.out.println(exceptionType);
            }
            System.out.println("--------------------------");
        }
    }
}




package com.fan.reflect;

import com.fan.model.User;

import java.lang.reflect.Constructor;
public class 获得一个构造方法并创建对象 {
    public static void main(String[] args) throws Exception{
        Class<User> userClass = User.class;
        //使用默认的构造方法创建对象,但JDK11以后就过期了,
//        User user = userClass.newInstance();
        //获得无参数的构造方法对象
//        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
//        //使用构造方法创建类的对象,调用无参数的构造方法
//        User user = declaredConstructor.newInstance();
//
        //获得有参数的构造方法对象
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class, String.class);
        //使用构造方法创建类的对象,调用有参数的构造方法
        User user = declaredConstructor.newInstance(11, "樊军刚", "123456");
        System.out.println(user);


    }
}


5.创建对象的俩种方式
(1) 通过字节码对象调用newInstance方法直接调用对象,但JDK11以后就过期了

       Class<User> userClass = User.class;
        //使用默认的构造方法创建对象,但JDK11以后就过期了,
        User user = userClass.newInstance();

(2)通过字节码生成构造器对象,再通过构造器对象调用newInstance()方法来生成对象

       Class<User> userClass = User.class;
       Constructor<User> declaredConstructor =userClass.getDeclaredConstructor(int.class, String.class, String.class);
        //使用构造方法创建类的对象,调用有参数的构造方法
        User user = declaredConstructor.newInstance(11, "樊军刚", "123456");
        System.out.println(user);

三.java反应的应用
1**.封装DButils的查询方法,可以用于查询所有的查询,相当于Mybatis的超级讲话版本**
代码:

public   <T>List<T> executeQuery(Class<T> cla,String sql,Object...params){
        try {
            this.getConn();
            ps=conn.prepareStatement(sql);
            if (params!=null&&params.length!=0){
                for (int i=0;i< params.length;i++){
                    ps.setObject(i+1,params[i]);
                }
            }
            rs=ps.executeQuery();
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            List<T> list = new ArrayList<>();
            while(rs.next()){
                T t = cla.getDeclaredConstructor().newInstance();
                for (int i=0;i<columnCount;i++){
                    Object value = rs.getObject(i + 1);
                    String catalogName = metaData.getCatalogName(i + 1);
                    Field declaredField = cla.getDeclaredField(catalogName);
                    String methodName = "set" + catalogName.substring(0, 1).toUpperCase() + catalogName.substring(1);
                    Method declaredMethod = cla.getDeclaredMethod(methodName, declaredField.getType());
                    declaredMethod.invoke(t, ConvertUtils.convert(value,declaredField.getType()));
                    list.add(t);
                }
                return list;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

2.封装Servlet,相当于超级简化版本的SpringMVC,当然了,我们考虑的情况非常少,框架要考虑的情况非常多,非常复杂

package com.fan.reflect.强化反射训练;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;

public class Tools {
     public  static  <T>  T encapsulationByRequest(Class<T> cla, HttpServletRequest  request) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, ParseException {
         //获得客户端提交的参数信息,获得一个Map集合key是参数名,值是参数值(字符串数组)
         Map<String, String[]> parameterMap = request.getParameterMap();
         //创建实体对象
         T t = cla.getDeclaredConstructor().newInstance();
         //遍历Map集合
         for (Map.Entry<String,String[]> entry:parameterMap.entrySet()){
             //规定:参数名和实体的属性名必须一致
             //根据参数名获得属性名
             String fieldName = entry.getKey();
             //判断是否存在参数值,如果不存在则继续下一次循环
             if (entry.getValue()==null||entry.getValue().length==0){
                 continue;
             }
             //获得参数值
             String[] value = entry.getValue();
             //根据属性名获得属性对象
             Field declaredField = cla.getDeclaredField(fieldName);
             //根据属性名获得方法名
             String  methodName="Set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
             //获得属性的类型
             Class<?> type = declaredField.getType();
             //根据方法名和参数列表获得方法对象
             Method method = cla.getDeclaredMethod(methodName, type);
             //根据属性的类型对值进行处理
             if (type==String.class){
                 method.invoke(t,value[0]);
             }else  if (type== Date.class){
                 java.util.Date date = new SimpleDateFormat("yyyy-MM-dd").parse(value[0]);
                 method.invoke(t,date);
             }else if (type==Integer.class){
                 method.invoke(t,Integer.parseInt(value[0]));
             }else  if (type.isArray()){
                 method.invoke(t,new Object[]{value});
             }
         }
      return   t;
     }
}

至此,java反射结束,创作不易,希望大家多多支持,我在此感谢大家了!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值