赞
踩
Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。
Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型
例如Person p = new Student();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实形态。而通过使用反射程序就能判断出该对象和类属于哪些类。
跳转链接:Class帮助文档
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。
我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类。
示列:
如图我们新建一个reflectdemo的包,下面再定义一个Student类
Student类 :
获得Class对象的三种方式:
在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的,即:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息。
第一种,使用 Class.forName(“类的全路径名”); 静态方法。
前提:已明确类的全路径名。
第二种,使用 .class 方法。
说明:仅适合在编译前就已经明确要操作的 Class
第三种,使用类对象的 getClass() 方法
示列:
通过打印地址可知,通过不同的方式获取的类地址是一样的,也就是获取到的是同一个类:
注意:所有和反射相关的包都在 import java.lang.reflect 包下面。
/** * 通过Class类的newInstance方法 获取 学生实例 */ public static void reflectNewInstance() { try { Class<?> c1=Class.forName("reflectdemo1.Student"); try { Student student=(Student) c1.newInstance(); System.out.println(student); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
注意,因为带有两个参数的Student类的构造方法属性是private私有的,
我们需要使用 constructor.setAccessible(true);
语句,参数传入ture,即可实现对private方法访问
注意反射中对两个参数的构造方法传参语句是String.class,int.class
,需要相应类型后.class
/** * 反射构造方法 */ public static void reflectPrivateConstructor(){ try { Class<?> c1=Class.forName("reflectdemo1.Student"); try { Constructor<?> constructor=c1.getDeclaredConstructor(String.class,int.class); constructor.setAccessible(true); try { Student student=(Student) constructor.newInstance("xxx",18); System.out.println(student); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
输出如下:
field.setAccessible(true);
,这样就运行访问了;/** * 反射属性 获取私有的 或者 公开的 */ public static void reflectPrivateField(){ try { Class<?> c1 = Class.forName("reflectdemo1.Student"); try { Student student=(Student) c1.newInstance(); try { Field field=c1.getDeclaredField("name"); field.setAccessible(true); field.set(student,"zhangsan"); System.out.println(student); } catch (NoSuchFieldException e) { e.printStackTrace(); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
输出如下:
function方法在Student类中是私有的,注意方法的使用;
传参方式为:"function", String.class
,前面function为方法名,后面为相应参数,注意.class
以及需要注意将访问权限进行修改 method.setAccessible(true);
实现正常访问
/** * 反射 私有或者公有的方法 */ public static void reflectPrivateMethod(){ try { Class<?> c1=Class.forName("reflectdemo1.Student"); try { Student student=(Student) c1.newInstance(); Method method= null; try { method = c1.getDeclaredMethod("function", String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } method.setAccessible(true); try { method.invoke(student,"我是私有方法的参数"); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
输出如下:
优点:
缺点:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。