后端框架(2):Java的反射机制

打印 上一主题 下一主题

主题 2077|帖子 2077|积分 6241

什么是java反射机制?

  回顾之前java步伐如何利用类
    1.分析,确定类名,属性名,方法......创建类
    2.创建类的对象
    3.利用
齐备都是已知的。
在步伐开辟中,在哪儿必要利用哪个类的对象,就在那儿创建这个类对象,去利用即可
这种写法对于业务开辟来说是没问题的。
但~是!,在一些组件 或者 在框架的开辟中,他们本身时不知道要处理哪些类
比方:jackson组件,我们给他什么类,他们就处理转换什么类
  1. new ObjectMapper().writeValueAsString(result)
复制代码
在web.xml中配置了哪些servlet类,tomcat就要创建哪些类对象
  1. <servlet-class>com.skw.dorm.web.LoginServlet</servlet-class>
  2. <servlet-class>com.skw.dorm.web.TestServlet</servlet-class>
复制代码
在mybatis中,给了什么类型,mybatis就可以将结果封装映射到给定的类的对象中
  1. <select id="findAdminById" parameterType="int" resultType="Admin">
复制代码
等等一系列,如许单一对着一个明确的类去利用。
问题:如果仅仅知道一个类的类名,可否动态得到类的定义信息,包括哪些方法, 属性等?
以前已知类名的利用方式,可以看做是正向利用类。
而框架必要只写一套步伐,就可以处理我们给他的任意类
框架必要对任意类处理时,只是知道类的名字,通过类的名字动态才去获取类中的信息。
把这种对类的利用方式,称为反向利用。也可以被称为:反射!
反射

  概念:

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
    Java反射机制的作用就是:可动态的获取类的信息
  要如何去实现Java的反射机制呢?

    起首了解Java反射相干的API:
        Java反射相干的类重要包括
                Class 类型
                Constructor 构造方法
                Method 方法
                Field 属性
        除了Class外,其他类都位于java.lang.reflect包中
        可见,反射API将类的类型、方法、属性都封装成了类,其中最重要的类是 Class,可以说,反射的利用都是从Class开始。
    1、Class类

        java.lang.Class
        一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被利用时都会创建一个Class对象。
        Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息。

Class类的对象,表示当前正在运行中的类和接口。

获得Class的三种方法

要利用Class类的方法,必须先获得该类的Class类的实例,获得Class 类实例的常用方法有如下三种
  1. //方式1:通过类的名称(包名+类名)来获取Class类
  2.         Class clazz1 = Class.forName(classname);
  3.         System.out.println(clazz1);
复制代码
  1. //方式2:通过只知道类来获取Class类
  2.         Class clazz2 = User.class;
复制代码
  1. //方式3:通过知道类的对象来获取Class类
  2.         User user = new User();
  3.         Class clazz3 = user.getClass();
复制代码
Class类的常用方法

方法名功能阐明static Class forName(String name)返回指定类名 name 的 Class 对象Object newInstance()调用缺省构造函数,返回该Class对象的一个实例getName()返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称Class [] getInterfaces()获取当前Class对象的接口Constructor[] getConstructors()返回一个包罗某些Constructor对象的数组Field[] getDeclaredFields()返回Field对象的一个数组Method getMethod(String name,Class … paramTypes)返回一个Method对象,此对象的形参类型为paramType
2、Constructor 构造方法

  1.         //使用反射机制时,只知道类的名称(包名+类名)
  2.         String classname = "com.ffyc.javareflect.User";
  3.         //1.通过类名,获得到类的Class对象
  4.         Class aClass = Class.forName(classname);
  5.         //2.通过类的Class对象,创建对象
  6.         Object obj = aClass.newInstance();
  7.         //获得类中的构造方法,通过构造方法api中的方法创建对象
  8.         Constructor constructor1 = aClass.getConstructor();  //获得指定的公共构造方法
  9.         Object obj1 = constructor1.newInstance();//无参构造方法
  10.         Constructor constructor2 = aClass.getConstructor(String.class,String.class);
  11.         Object obj2 = constructor2.newInstance("张三","1111");//有参构造方法
  12.         System.out.println(obj1);
  13.         System.out.println(obj2);
  14.         Constructor[] constructors = aClass.getConstructors();//获得所有公共的构造方法
  15.         //虽然可以获取私有构造方法,但是一般不建议操作私有成员,因为打破了封装性
  16.         aClass.getDeclaredConstructor();//获得类中任意的构造方法,包含私有的
复制代码
                         

3、Method 方法

  1.         //使用反射机制时,只知道类的名称(包名+类名)
  2.         String classname = "com.ffyc.javareflect.User";
  3.         //1.通过类名,获得到类的Class对象
  4.         Class aClass = Class.forName(classname);
  5.         //2.通过类的Class对象,创建对象
  6.         Object obj = aClass.newInstance();
  7.         //获得类中指定名称的成员方法
  8.         Method method = aClass.getMethod("eat" );
  9.         //调用访问
  10.         method.invoke(obj);
复制代码
                                ​  ​​​​​​​                 

4、Field 属性

  1.         //使用反射机制时,只知道类的名称(包名+类名)
  2.         String classname = "com.ffyc.javareflect.User";
  3.         //1.通过类名,获得到类的Class对象
  4.         Class aClass = Class.forName(classname);
  5.         //2.通过类的Class对象,创建对象
  6.         Object obj = aClass.newInstance();
  7.         //获得类中成员变量
  8.         //Field accountField = aClass.getField("account");//获得指定名称的公共的成员变量
  9.         Field accountField = aClass.getDeclaredField("account");//获得指定名称的成员变量,包含私有的
  10.               accountField.setAccessible(true);//设置允许直接访问操作私有成员
  11.               accountField.set(obj,"admin");
  12.         System.out.println(obj);
复制代码
        ​​​​​​​           

模拟框架拿任意一个类的信息

  1.         //使用反射机制时,只知道类的名称(包名+类名)
  2.         String classname = "com.ffyc.javareflect.User";
  3.         //1.通过类名,获得到类的Class对象
  4.         Class aClass = Class.forName(classname);
  5.         //2.通过类的Class对象,创建对象
  6.         Object obj = aClass.newInstance();
  7.         //演示通过属性的get和set方法,对类中私有属性进行赋值取值操作
  8.         //模拟从数据库中查询到的数据
  9.         HashMap<String,String> map = new HashMap<>();
  10.         map.put("account", "admin");
  11.         map.put("password", "1111");
  12.         //先拿到类中所有的私有属性
  13.         Field[] declaredFields = aClass.getDeclaredFields();
  14.         for (Field field : declaredFields){
  15.             //根据属性名,生成Set方法名称
  16.             String setmethod = "set"+field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
  17.             //通过Class对象,获得对应的Set方法对象
  18.             Method setmethodobj = aClass.getMethod(setmethod,field.getType());
  19.             //调用Set方法
  20.             setmethodobj.invoke(obj, map.get(field.getName()));
  21.         }
  22.         System.out.println(obj);
复制代码
        ​​​​​​​        ​​​​​​​        

模拟一个简朴的json转换格式

  1. public class JsonUtil {
  2.     public static String objectToJson(Object object) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
  3.         Class aclass = object.getClass();
  4.         Field[] declaredFields = aclass.getDeclaredFields();
  5.         String json = "{";
  6.         for (Field field : declaredFields){
  7.             //根据属性名,生成Get方法名称
  8.             String getmethod = "get"+field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
  9.             //通过Class对象,获得对应的Get方法对象
  10.             Method getmethodobj = aclass.getMethod(getmethod);
  11.             //调用Get方法
  12.             json += field.getName() +":"+ (String) getmethodobj.invoke(object) + ",";
  13.         }
  14.         json = json.substring(0, json.length() - 1) + "}";
  15.         return json;
  16.     }
  17.     public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
  18.         User user = new User();
  19.              user.setAccount("admin");
  20.              user.setPassword("1111");
  21.         Car car = new Car();
  22.             car.setName("宝马");
  23.             car.setColor("红色");
  24.         System.out.println(JsonUtil.objectToJson(user));
  25.         System.out.println(JsonUtil.objectToJson(car));
  26.     }
  27. }
复制代码
        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​      

反射的优缺点:

    优点:

            1、增加步伐的机动性,可以在运行的过程中动态对类进行修改和利用
            2、提高代码的复用率
            3、可以在运行时轻松获取任意一个类的方法、属性,而且还能通过反射进行动态调用
    缺点:

            1、反射会涉及到动态类型的解析,导致性能要比非反射调用更低
            2、利用反射技术通常要在一个没有安全限制的步伐运行.
            3、反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的封装性

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

篮之新喜

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表