java反射基础

反射的概念主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java反射的应用
 1. Spring框架:IOC(控制反转)
 2. Hibernate框架:关联映射等
 3. 白盒测试

相关API

java.lang包下
 1. Class<T>:表示一个正在运行的 Java 应用程序中的类和接口,是Reflection的起源

java.lang.reflect包下
 1. Field 类:代表类的成员变量(也称类的属性)
 2. Method类:代表类的方法
 3. Constructor 类:代表类的构造方法
 4. Array类:提供了动态创建数组,以及访问数组的元素的静态方法

Class<T>
 类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象

  Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass方法自动构造的,因此不能显式地声明一个Class对象

  Class是Reflection起源。要想操纵类中的属性和方法,都必须从获取Class object 开始

创建测试单元

1610803477531.png

1610803477572.png

1610803477605.png

最后,随便在某个类中写一个方法在方法上加上 @org.junit.Test即可

动态实例化

为什么要用动态实例化
 1. 如果用new的方式直接创建对象,那就意味着程序已经写死了,java程序一般都是运行在千里之外的服务器上,现在我要千里之外动态的创建一个人User,我不可能把这个人创建出来,再重新部署上去,这就需要动态的创建对象。

创建对象的类有两种方式
 1. User.class:直接创建对象的类
 2. Class.forName(className):通过类的名字创建对象的类

动态方法调用

获得当前类以及超类的public Method:
Method[] arrMethods = classType. getMethods();

获得当前类申明的所有Method:
Method[] arrMethods = classType. getDeclaredMethods();

获得当前类以及超类指定的public Method:
Method method = classType. getMethod(String name, Class<?>… parameterTypes);

获得当前类申明的指定的Method:
Method method = classType. getDeclaredMethod(String name, Class<?>… parameterTypes)

通过反射动态运行指定Method:
Object obj = method. invoke(Object obj, Object… args)

为了方便测试,添加单元测试Junit

动态获取类和执行类中方法的思路

获取类->Class.forName

 1. 获取类对象后,这个Class类对象有很多方法,比如获取全部的类方法getDeclaredMethods()
 2. 我们可以通过这个类创建实例对象,newInstance()

通过获取到的类,获取类中的方法->getMethod(methodName, new Class[] {pc})
 1. 参数1:方法名字
 2. 参数2:这是一个类数组,里面存放方法的参数类型,我们可以通过Class.forName(paramType),来获取到一个参数的类型,比如paramType=”java.lang.String”

执行获取到的方法->invoke()
 1. 第一个参数传实例对象,第二个传参数

动态属性访问

代码可以看当前目录下的image里的图片

通过反射调用Field变量

获得当前类以及超类的public Field:
Field[] arrFields = classType. getFields();

获得当前类申明的所有Field:
Field[] arrFields = classType. getDeclaredFields();

获得当前类以及超类指定的public Field:
Field field = classType. getField(String name);

获得当前类申明的指定的Field:
Field field = classType. getDeclaredField(String name);

通过反射动态设定Field的值:
fieldType.set(Object obj, Object value);

通过反射动态获取Field的值:
Object obj = fieldType. get(Object obj) ;

Field是属性
只要用到反射,先获得Class Object

  没有方法能获得当前类的超类的private方法和属性,你必须通过getSuperclass()找到超类以后再去尝试获得通常情况即使是当前类,private属性或方法也是不能访问的,你需要设置压制权限setAccessible(true)来取得private的访问权。但这样就破坏了面向对象的规则,所以除非万不得已,尽量少用。

更多反射相关内容,百度一下,你就知道

获取类名

  1. Class clazz = Class.forName(path);
  2. clazz.getName();// 获取完整类名com.sg.myReflection.bean.User
  3. clazz.getSimpleName();// 直接获取类名 User

反射自动生成SQL语句

  编写给任意对象,自动生成SQL语句insert into,对象的类,使用一个对象,生成一个SQL语句,假设表名和类名相同。返回的SQL语句格式为:

INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,….)

获取SQL语句方法的大概思路:
 1. 定义一个可变的字符串StringBuffer
 2. 使用append()方法对字符串进行追加
 3. 使用反射获取对象类名,类中的属性名称