反射概述
1. 反射(reflection)的概念是由Smith于1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。通俗的讲就是反射可以在运行时根据执行的类名获得类的信息
2. Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
3. 想要解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
4. 反射是框架设计的灵魂(使用前提条件:必须先得到代表的字节码为Class,Class类用于表示.class文件(字节码))
通过反射获取Class实例的三种方式:
1. 对象.getClass()
2. 类名.class
3. Class.forName("全限定名")
Class<?> cls = Class.forName("demo1.Student");
newInstance() 创建此Class对象所表示的类的一个新实例
Object newInstance = cls.newInstance("老三",18);
第三种和前两种的区别:
1.前两种必须明确类型
2.第三种是你只要提供这种类型的字符串就行,这种扩展性更强,我不需要知道你的类,我只提供字符串,按照配置文件加载就可以了
通过反射获取接口和父类
1. 获取接口 getInterfaces()
Class<?>[] interfaces = cls.getInterfaces();
2. 获取父类 getSuperclass()
Class<?> superclass = cls.getSuperclass();
通过反射获取运行时类中构造
1. getConstructor(Class<?>... parameterType) 获取指定公共构造(包括父类)
Constructor<?> constructor = cls.getConstructor(String.class,int.class,String.class);
2. getConstructors() 获取本类的公共构造(包括父类)
Constructor<?>[] constructors = cls.getConstructors();
3. getDeclaredConstructor(Class<?>... parameterTypes) 获取本类指定的构造(共有或私有,但不包括父类)v
Constructor<?> con2 = cls.getDeclaredConstructor(String.class,int.class);
4. getDeclaredConstructors() 获取本类所有的构造(共有或私有,但不包括父类)
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
加Declared和不加Declared区别?
加Declared可以获取本类所有的(包括私有,但不包括父类)东西,不加Declared获取本类以及父类公有的(不包括私有,但包括父类)东西
加s和不加s区别?
加s获取的是多个,返回数组,不加s返回单个
通过反射获取运行时类中成员变量
getFields() 获取本类以及父类的所有公共属性(只能获取公有的)
Field[] fields2 = cls.getFields(); for (Field field2 : fields2) { //获取访问修饰符 int modifiers2 = field2.getModifiers(); String string2 = Modifier.toString(modifiers2); //获取属性类型 Class<?> type2 = field2.getType(); String simpleName2 = type2.getSimpleName(); //获取属性名称 String name2 = field2.getName(); //获取属性值 Object object2 = field2.get(obj); System.out.println(string2+" "+simpleName2+" "+name2+" "+object2); }
getField(String name) 获取本类以及父类中指定的属性(只能获取公有的)
Field field2 = cls.getField("tName");
getDeclareFields() 获取本类以及父类的所有属性(包括私有)
Field[] fields = cls.getDeclaredFields(); //遍历属性 for (Field field : fields) { field.setAccessible(true); //获取访问修饰符 int modifiers = field.getModifiers(); String string = Modifier.toString(modifiers); //获取属性类型 Class<?> type = field.getType(); String simpleName = type.getSimpleName(); //获取属性名称 String name = field.getName(); //获取属性值 Object value = field.get(obj); System.out.println(string+" "+simpleName+" "+name+" "+value); //设置属性值 if("name".equals(name)) { field.set(obj, "阿莲"); }else if("age".equals(name)) { field.set(obj, 17); }else if("love".equals(obj)) { field.set(obj, "喜欢老王"); } }
getDeclareField(String name) 获取本类以及父类的指定属性(包括私有)
Field field = cls.getDeclaredField("name");
常用方法:
set(Object obj,Object value)
第一个参数:指定对象
if("name".equals(name)) { field.set(obj, "阿莲"); }else if("age".equals(name)) { field.set(obj, 17); }else if("love".equals(obj)) { field.set(obj, "喜欢老王"); }
get(Object obj) 返回指定对象上此Field表示的字段值
参数:指定的对象
通过反射获取运行时类中成员方法
getDeclaredMethods() 获取本类所有的成员方法(包括私有)
Method[] methods = cls.getDeclaredMethods(); //遍历方法 for (Method method : methods) { //获取访问修饰符 int modifiers = method.getModifiers(); String string = Modifier.toString(modifiers); //获取返回值类型 Class<?> type = method.getReturnType(); String simpleName = type.getSimpleName(); //获取方法名称 String name = method.getName(); //获取参数列表 Class<?>[] parameterTypes = method.getParameterTypes(); for (Class<?> class1 : parameterTypes) { System.out.println(class1.getSimpleName()); } System.out.println(string+" "+simpleName+" "+name); //调用方法 //有个问题,在循环内部直接调用方法,那么每个方法都会执行,但是我们方法中的参数不一样,所以这个如果需要调用方法需判断 if("setName".equals(name)) { //调用方法 method.invoke(student, "老王"); //方法的对象,调用的参数 } } System.out.println(student);
getDeclaredMethod(String name,Class<?>... parameterTypes) 获取本类指定的成员方法(包括私有)
Method method = cls.getDeclaredMethod("toString");
getMethods() 获取本类以及父类所有的公共成员方法(只能获取公有的)
Method[] methods2 = cls.getMethods();
getMethod(String name,Class<?>... parameterTypes) 获取本类以及父类指定的公共方法(只能获取公有的)
Method method2 = cls.getMethod("show", String.class);
invoke(Object obj,Object...args) 调用方法
第一个参数:调用哪个对象的方法
第二个参数:需要设置的值
if("setName".equals(name)) { //调用方法 method.invoke(student, "老王"); //方法的对象,调用的参数 }
反射常用的方法
getName() 获取名称
String name = method.getName();
getSimpleName() 获取简称
Class<?> type = method.getReturnType();
String simpleName = type.getSimpleName();
getModifiers() 获取访问修饰符
int modifiers = method.getModifiers(); String string = Modifier.toString(modifiers);
getParameterTypes() 获取参数列表
Class<?>[] parameterTypes = method.getParameterTypes(); for (Class<?> class1 : parameterTypes) { System.out.println(class1.getSimpleName()); }