框架底层的那些不为人知的密码之Java反射机制
一、反射的概叙
什么是Java的反射机制?
反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行的时候才动态加载类,并且对于任意一个类,都能够知道这个类的所有属性和方法,调用方法/访问属性,不需要提前在编译期知道运行的对象是谁,他允许运行中的Java程序获取类的信息,并且可以操作类或对象内部属性。程序中对象的类型一般都是在编译期就确定下来的,而当我们的程序在运行时,可能需要动态的加载一些类,这些类因为之前用不到,所以没有加载到jvm,这时,使用Java反射机制可以在运行期动态的创建对象并调用其属性,它是在运行时根据需要才加载。
Java反射机制的作用?
允许编程人员在对类未知的情况下,获取类相关信息的方式变得更加多样灵活,调用类中相应方法,是Java增加其灵活性与动态性的一种机制(从.class --> .java)。
反射机制的优缺点?
优点:
使用反射,我们就可以在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
缺点:
1、性能问题。
Java反射机制中包含了一些动态类型,所以Java虚拟机不能够对这些动态代码进行优化。因此,反射操作的效率要比正常操作效率低很多。我们应该避免在对性能要求很高的程序或经常被执行的代码中使用反射。而且,如何使用反射决定了性能的高低。如果它作为程序中较少运行的部分,性能将不会成为一个问题。
2、安全限制。
使用反射通常需要程序的运行没有安全方面的限制。如果一个程序对安全性提出要求,则最好不要使用反射。
3、程序健壮性。
反射允许代码执行一些通常不被允许的操作,所以使用反射有可能会导致意想不到的后果。反射代码破坏了Java程序结构的抽象性,所以当程序运行的平台发生变化的时候,由于抽象的逻辑结构不能被识别,代码产生的效果与之前会产生差异。同时也会使得程序的代码复杂度上升,所以还要我们慎重的使用它。
二、反射的基本使用
sun为反射机制提供的常用的类
Java.lang.Class;
Java.lang.reflect.Constructor;
Java.lang.reflect.Field;
Java.lang.reflect.Method;
Java.lang.reflect.Modifier;
反射常用的API?
对象. setAccessible(true);// 修改访问权限
Class:
类对象.getField("属性名"); //获取公开属性
类对象.getDeclaredField("属性名"); //获取私有属性
类对象.getMethod("方法名", null); //通过指定方法名称获取公开无参方法对象
类对象.getMethods(); //获取所有公开方法对象
类对象.getDeclaredMethods(); //获取所有方法对象
类对象.getDeclaredMethod("方法名", 方法参数的类型......); //通过指定方法名称获取私有有参方法对象
类对象.getConstructor(构造参数类型); //调用公开有参构造
类对象.getDeclaredConstructor(构造参数类型); //调用私有有参构造
类对象.isInstance(obj);// 判断是否是某个类的实例
Field:
属性对象.getName(); //获取属性名
属性对象.getType(); ////获取属性的类型
属性对象.getModifiers(); //获取属性的修饰符
属性对象.set(obj,obj); //设置属性值 1:类实例化对象 要设置的参数值
……
Method:
方法对象.invoke(类实例化对象, 方法的参数数组); //执行方法
Constructor:
NewInstance();//通过构造获取到类的实例对象
三、站在反射的角度看待ORM框架
ORM框架的简单实现(JDBC部分):
jdbc连接类:
CRUD基类:
得到增加SQL的方法:
增加方法:
查询方法:
从以上代码可以看出我们只需要传入一个Object对象就可以对数据库进行CRUD操作,Object对象是可以为任意实体类的,所以说这个类是我们通过反射的机制来写的一个对所有数据库表CRUD的基类。
类似与ORM框架Hibernate、Mybatis框架底层都是使用反射机制来保证框架的灵活性。我曾阅读过这些框架的源码,底层实现几乎就是使用这样的方式实现的,只是我这个实现写的有点简单,大家可以参考我的这篇文章再去看一下框架的源码,试着自己写一个ORM框架。