一、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
1、获取Class对象
获取类对象的三种方式,1已经可以创建实体类了,再用反射,多此一举;2需要配置文件支持;3通过全限定名获取,一般常用
2获取构造器
请注意图中的修饰符和参数
@Test//获取构造器 public void objTest3() { System.out.println("**********************************获取所有构造器**********************************"); Class<?> aClass = null; try { aClass = Class.forName("com.example.reflex.Student"); } catch (ClassNotFoundException e) { e.printStackTrace(); } Constructor<?>[] constructors = aClass.getConstructors(); System.out.println("**********************************获取所有公共构造器**********************************"); for (Constructor<?> constructor : constructors) { System.out.println("构造器输出 : " + constructor); } System.out.println("**********************************获取所有构造器(包括私有,受保护的)**********************************"); Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println("构造器输出 : " + declaredConstructor); } System.out.println("**********************************获取默认的构造器(公有无参)**********************************"); Constructor<?> constructor = null; try { constructor = aClass.getConstructor(null); } catch (NoSuchMethodException e) { e.printStackTrace(); } System.out.println("构造器输出:" + constructor); }
控制台输出结果
getConstructors 获取所有公共的构造器;getDeclaredConstructors 获取所有构造器,包括私有,受保护的
获取私有构造器,并调用
@Test//获取私有构造器并调用 public void objTest4() { Class<?> aClass = null; try { aClass = Class.forName("com.example.reflex.Student"); } catch (ClassNotFoundException e) { e.printStackTrace(); } Constructor<?> declaredConstructor = null; try { //反射获取构造方法对象 declaredConstructor = aClass.getDeclaredConstructor(int.class);//String.class char.class int.class } catch (NoSuchMethodException e) { e.printStackTrace(); } System.out.println("构造方法:" + aClass); declaredConstructor.setAccessible(true);//开启暴力访问,忽略访问修饰符 try { //构造方法中添加属性、返回T类型 Object newInstance = declaredConstructor.newInstance(18); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
控制台输出结果
getDeclaredConstructor(int.class) 指定获取构造器,参数int
反射回的对象.setAccessible(true); 开启暴力模式,忽略修饰符
3获取成员变量
@Test//获取成员变量 public void Fields() { Class<?> aClass = null; try { aClass = Class.forName("com.example.reflex.reflexOfEntity"); } catch (ClassNotFoundException e) { e.printStackTrace(); } Field[] fields = aClass.getFields(); System.out.println("**********************************获取公有成员变量**********************************"); for (Field field : fields) { System.out.println("成员变量:" + field); } System.out.println("**********************************获取所有成员变量(包括私有、受保护、默认的)**********************************"); Field[] declaredFields = aClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("成员变量:" + declaredField); } }
控制台输出结果
注意修饰符和成员变量名称
类对象.getFields 获取所有公有的成员变量; 类对象.getDeclaredFields 获取所有的成员变量,包括私有的,受保护的,默认的;
@Test//获取私有成员变量并调用 public void Fields2() { System.out.println("**********************************获取私有属性并调用**********************************"); Class<?> aClass = null; try { aClass = Class.forName("com.example.reflex.reflexOfEntity"); } catch (ClassNotFoundException e) { e.printStackTrace(); } Field[] declaredFields = aClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("遍历所有成员变量:" + declaredField); } //private java.lang.String com.example.reflex.reflexOfEntity.phoneNum 获取到的私有成员变量 Field phoneNum = null; try { phoneNum = aClass.getDeclaredField("phoneNum"); } catch (NoSuchFieldException e) { e.printStackTrace(); } System.out.println("输出私有成员变量:" + phoneNum); //反射类对象 Object newInstance = null; try { newInstance = aClass.getConstructor().newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } phoneNum.setAccessible(true);//开启暴力模式,忽略修饰符 try { phoneNum.set(newInstance,"222"); } catch (IllegalAccessException e) { e.printStackTrace(); } reflexOfEntity reflexOfEntity = (reflexOfEntity) newInstance;//获取类实例化对象 System.out.println("输出对象,查看phoneNum属性:" + reflexOfEntity); }
控制台输出
私有的成员变量 phoneNum 被赋值
类对象.getConstructor().newInstance(); 获取类实例化对象
成员变量对象.set(类实例化对象,"222");
aClass.getDeclaredField("phoneNum"); aClass(类对象)phoneNum (成员变量名称)
4获取方法
@Test//获取方法 public void testMethod() { //获取类对象 Class<?> aClass = null; try { aClass = Class.forName("com.example.reflex.reflexOfMethod"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("**********************************获取所有共有方法**********************************"); //获取所有的共有方法 Method[] methods = aClass.getMethods(); for (Method method : methods) { System.out.println("共有方法:" + method); } System.out.println("**********************************获取所有(自定义)方法(包括私有,默认,受保护的)**********************************"); //获取所有方法 Method[] declaredMethods = aClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("所有方法:" + declaredMethod); } }
控制台输出
注意方法名,修饰符,包名
getMethods();获取所有共有方法,包括Java内设方法 ; getDeclaredMethods()获取所有自定义方法,包括私有的,受保护的,默认的;
@Test//获取指定方法,并调用 public void testMethod2() { //获取类对象 Class<?> aClass = null; try { aClass = Class.forName("com.example.reflex.reflexOfMethod"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("获取类对象:" + aClass); System.out.println("**********************************获取所有(自定义)方法(包括私有,默认,受保护的)**********************************"); //获取自定义所有方法 Method[] declaredMethods = aClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("查看方法:" + declaredMethod); } //public void com.example.reflex.reflexOfMethod.show1(java.lang.String)公有方法show1 //private java.lang.String com.example.reflex.reflexOfMethod.show4(int)私有方法show4 //调用指定方法 Method show1 = null; try { show1 = aClass.getMethod("show1", String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } System.out.println("获得方法:" + show1); //获取类实例化对象 Object newInstance = null; try { newInstance = aClass.getConstructor().newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } Object chenyb = null; try { chenyb = show1.invoke(newInstance, "Chenyb"); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println("调用方法show1,输出返回值:" + chenyb); Method show4 = null; try { show4 = aClass.getDeclaredMethod("show4", int.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } System.out.println("获得私有方法:" + show4); //调用类对象 show4.setAccessible(true);//暴力调用,忽略修饰符 Object invoke = null; try { invoke = show4.invoke(newInstance, 18); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println("调用方法show4,输出返回值:" + invoke); }
控制台输出
-
以上环节,注意开启暴力权限的步奏,和参数类型 类型 类型
2018-09-05
Chenyb 随笔记录,方便自己学习(学习到了Java 线程&反射,才感觉自己java 才刚刚入门)