1、什么是反射?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象
2、使用反射
2.1、加载过程
反射就是把java类中的各种成分映射成一个个java对象,如图是类的正常加载过程:反射的原理在于class对象
Class对象的由来就是将字节码文件.class加载到内存中,并为之创建一个class对象
2.2、怎么使用反射?
一、获取 Class 对象的 3 种方法:
1、调用某个对象的getClass()方法
Person p = new Person;Class c = p.getClass();
2、调用某个类的class属性来获取该类对应的class对象
Class c = Person.class;
3、使用Class类中的forName()静态方法
Class c = Class.forName("类的全路径");
package fanshe;/*** 获取Class对象的三种方式* 1 Object ——> getClass();* 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性* 3 通过Class类的静态方法:forName(String className)(常用)**/public class Fanshe {public static void main(String[] args) {//第一种方式获取Class对象Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。Class stuClass = stu1.getClass();//获取Class对象System.out.println(stuClass.getName());//第二种方式获取Class对象Class stuClass2 = Student.class;System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个//第三种方式获取Class对象try {Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象} catch (ClassNotFoundException e) {e.printStackTrace();}}}
二、通过反射获取构造方法
getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个
Test test = new Test();Class c4 = test.getClass();Constructor[] constructors ;constructors = c4.getDeclaredConstructors();
getModifiers可以得到构造方法的类型
getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组
如果想获取所有构造方法以及每个构造方法的参数类型,可以有如下代码:
for (int i = 0; i < constructors.length; i++) {System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数:");Class[] parametertypes = constructors[i].getParameterTypes();for (int j = 0; j < parametertypes.length; j++) {System.out.print(parametertypes[j].getName() + " ");}System.out.println("");}
getConstructors方法获取类中 所有的public类型的构造方法
getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。
获取无参构造方法直接不传参数
try {constructors = c4.getDeclaredConstructor();System.out.print(Modifier.toString(constructors.getModifiers()) + );} catch (NoSuchMethodException e) {e.printStackTrace();}
获取有两个参数分别为int和String类型的构造方法
Class[] p = {int.class,String.class};try {constructors = c4.getDeclaredConstructor(p);System.out.print(Modifier.toString(constructors.getModifiers()) + "参数:");Class[] parametertypes = constructors.getParameterTypes();for (int j = 0; j < parametertypes.length; j++) {System.out.print(parametertypes[j].getName() + " ");}} catch (NoSuchMethodException e) {e.printStackTrace();}
三、调用构造方法
主要借助于newInstance方法
public Test(int age, String name) {
this.age = age;
this.name = name;
System.out.println("hello" + name + "i am" + age);
}
private Test(String name) {
this.name = name;
System.out.println("My Name is" +
name);
}
调用public方法
Class[] p = {int.class,String.class};
constructors = c4.getDeclaredConstructor(p);
constructors.newInstance(24,"HuangLinqing");
调用私有构造方法呢,需要先设置constructors.setAccessible(true);
Class[] p = {String.class};
constructors = c4.getDeclaredConstructor(p);
constructors.setAccessible(true);
constructors.newInstance("HuangLinqing");
四、调用类的私有方法
getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型
Method method = c4.getDeclaredMethod("方法名",参数类型);
通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数
method.invoke(test,"AAA");
五、获取类的私有字段并修改值
通过反射得到类的实例之后先获取字段
Field field = c4.getDeclaredField("name");
field.setAccessible(true);
field.set(o,"KOBE");
o是我们上面通过反射构造方法获取的实例
注意的是我们修改了name的值只对当前的实例对象有效
3、反射封装类
package jnidemo.hlq.com.hookdemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author Huanglinqing
* @date 2019/4/28
*/
public class Reflex {
/**
* 获取无参构造函数
* @param className
* @return
*/
public static Object createObject(String className) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
try {
Class r = Class.forName(className);
return createObject(r, pareTyples, pareVaules);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取无参构造方法
* @param clazz
* @return
*/
public static Object createObject(Class clazz) {
Class[] pareTyple = new Class[]{};
Object[] pareVaules = new Object[]{};
return createObject(clazz, pareTyple, pareVaules);
}
/**
* 获取一个参数的构造函数 已知className
*
* @param className
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object createObject(String className, Class pareTyple, Object pareVaule) {
Class[] pareTyples = new Class[]{pareTyple};
Object[] pareVaules = new Object[]{pareVaule};
try {
Class r = Class.forName(className);
return createObject(r, pareTyples, pareVaules);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取单个参数的构造方法 已知类
*
* @param clazz
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
Class[] pareTyples = new Class[]{pareTyple};
Object[] pareVaules = new Object[]{pareVaule};
return createObject(clazz, pareTyples, pareVaules);
}
/**
* 获取多个参数的构造方法 已知className
* @param className
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
try {
Class r = Class.forName(className);
return createObject(r, pareTyples, pareVaules);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取构造方法
*
* @param clazz
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
try {
Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
ctor.setAccessible(true);
return ctor.newInstance(pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取多个参数的方法
* @param obj
* @param methodName
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
if (obj == null) {
return null;
}
try {
//调用一个private方法 //在指定类中获取指定的方法
Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
method.setAccessible(true);
return method.invoke(obj, pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取一个参数的方法
* @param obj
* @param methodName
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
Class[] pareTyples = {pareTyple};
Object[] pareVaules = {pareVaule};
return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
}
/**
* 获取无参方法
* @param obj
* @param methodName
* @return
*/
public static Object invokeInstanceMethod(Object obj, String methodName) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
}
/**
* 无参静态方法
* @param className
* @param method_name
* @return
*/
public static Object invokeStaticMethod(String className, String method_name) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
}
/**
* 获取一个参数的静态方法
* @param className
* @param method_name
* @param pareTyple
* @param pareVaule
* @return
*/
public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
Class[] pareTyples = new Class[]{pareTyple};
Object[] pareVaules = new Object[]{pareVaule};
return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
}
/**
* 获取多个参数的静态方法
* @param className
* @param method_name
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
try {
Class obj_class = Class.forName(className);
return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 无参静态方法
* @param method_name
* @return
*/
public static Object invokeStaticMethod(Class clazz, String method_name) {
Class[] pareTyples = new Class[]{};
Object[] pareVaules = new Object[]{};
return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
}
/**
* 一个参数静态方法
* @param clazz
* @param method_name
* @param classType
* @param pareVaule
* @return
*/
public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
Class[] classTypes = new Class[]{classType};
Object[] pareVaules = new Object[]{pareVaule};
return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
}
/**
* 多个参数的静态方法
* @param clazz
* @param method_name
* @param pareTyples
* @param pareVaules
* @return
*/
public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
try {
Method method = clazz.getDeclaredMethod(method_name, pareTyples);
method.setAccessible(true);
return method.invoke(null, pareVaules);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object getFieldObject(String className, Object obj, String filedName) {
try {
Class obj_class = Class.forName(className);
return getFieldObject(obj_class, obj, filedName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static Object getFieldObject(Class clazz, Object obj, String filedName) {
try {
Field field = clazz.getDeclaredField(filedName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
try {
Field field = clazz.getDeclaredField(filedName);
field.setAccessible(true);
field.set(obj, filedVaule);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
try {
Class obj_class = Class.forName(className);
setFieldObject(obj_class, obj, filedName, filedVaule);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Object getStaticFieldObject(String className, String filedName) {
return getFieldObject(className, null, filedName);
}
public static Object getStaticFieldObject(Class clazz, String filedName) {
return getFieldObject(clazz, null, filedName);
}
public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
setFieldObject(classname, null, filedName, filedVaule);
}
public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
setFieldObject(clazz, null, filedName, filedVaule);
}
}
