目录
Java 反射机制是Java语言一个很重要的特性,它使得Java具有了“动 态性”。在Java程序运行时,对于任意的一个类,我们能不能知道这 个类有哪些属性和方法呢?对于任意的一个对象,我们又能不能调 用它任意的方法?答案是肯定的!这种动态获取类的信息以及动态 调用对象方法的功能就来自于Java 语言的反射(Reflection)机 制。
简单来说两个作用,RTTI(运行时类型识别)和DC(动态创建)。 我们知道反射机制允许程序在运行时取得任何一个已知名称的class 的内部信息,包括其modifiers(修饰符),fields(属性),methods(方 法)等,并可于运行时改变fields内容或调用methods。那么我们便 可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间 进行源代码链接,降低代码的耦合度;还有动态代理的实现等等; 但是需要注意的是反射使用不当会造成很高的资源消耗!
Users user = new Users();
实际上,我们在加载任何一个类时都会在方法区中建立“这个类对应 的Class对象”,由于“Class对象”包含了这个类的整个结构信息,所 以我们可以通过这个“Class对象”来操作这个类。 我们要使用一个类,首先要加载类;加载完类之后,在堆内存中, 就产生了一个 Class 类型的对象(一个类只有一个 Class 对象), 这个对象就包含了完整的类的结构信息。我们可以通过这个对象知 道类的结构。这个对象就像一面镜子,透过这个镜子可以看到类的 结构,所以,我们形象的称之为:反射。 因此,“Class对象”是反射 机制的核心。
获取Class对象的三种方式
1、通过getClass()方法;
2、通过.class 静态属性;
3、通过Class类中的静态方法forName();
- public class Users {
- private String username;
- private int userage;
- public String getUsername() {
- return username;
- }
- public void setUsername(String username)
- {
- this.username = username;
- }
- public int getUserage() {
- return userage;
- }
- public void setUserage(int userage) {
- this.userage = userage;
- }
- }
- * 通过getClass()方法获取该类的Class对象
- */
- public class GetClass1 {
- public static void main(String[] args) {
- Users users = new Users();
- Users users1 = new Users();
- Class clazz = users.getClass();
- System.out.println(clazz);
- System.out.println(clazz.getName());
- System.out.println(users.getClass() == users1.getClass());
- }
- }
- /**
- * .class静态属性获取Class对象
- */
- public class GetClass2 {
- public static void main(String[] args) {
- Class clazz = Users.class;
- Class clazz2 = Users.class;
- System.out.println(clazz);
- System.out.println(clazz.getName());
- System.out.println(clazz == clazz2);
- }
- }
- /**
- * 通过Class.forName("class Name")获取Class对象
- */
- public class GetClass3 {
- public static void main(String[] args)throws Exception {
- Class clazz = Class.forName("com.bjsxt.Users");
- Class clazz2 = Class.forName("com.bjsxt.Users");
- System.out.println(clazz);
- System.out.println(clazz.getName());
- System.out.println(clazz == clazz2);
- }
- }
方法介绍
方法使用
修改Users类
- public class Users {
- private String username;
- private int userage;
- public Users(){}
- public Users(String username,int userage){
- this.username= username;
- this.userage=userage;
- }
-
- public Users(String username){
- this.username= username;
- }
-
- private Users(int userage){
- this.userage = userage;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username)
- {
- this.username = username;
- }
-
- public int getUserage() {
- return userage;
- }
- public void setUserage(int userage) {
- this.userage = userage;
- }
- }
获取构造方法
- public class GetConstructor {
- public static void main(String[] args)throws Exception {
- Class clazz = Users.class;
- Constructor[] arr = clazz.getDeclaredConstructors();
- for(Constructor c:arr){
- System.out.println(c);
- }
- System.out.println("---------------------");
- Constructor[] arr1 = clazz.getConstructors();
- for(Constructor c:arr1){
- System.out.println(c);
- }
- System.out.println("------------------------");
- Constructor c = clazz.getDeclaredConstructor(int.class);
- System.out.println(c);
- System.out.println("------------------------");
- Constructor c1 = clazz.getConstructor(null);
- System.out.println(c1);
- }
- }
- public class GetConstructor2 {
- public static void main(String[] args)throws Exception {
- Class clazz = Users.class;
- Constructor constructor = clazz.getConstructor(String.class,int.class);
- Object o = constructor.newInstance("OldLu",18);
- Users users = (Users)o;
- System.out.println(users.getUsername()+"\t"+ users.getUserage());
- }
- }
修改Users类
- public class Users {
- private String username;
- public int userage;
- public Users(){
- }
-
- public Users(String username,int userage){
- this.username= username;
- this.userage=userage;
- }
-
- public Users(String username){
- this.username= username;
- }
-
- private Users(int userage){
- this.userage = userage;
- }
-
- public String getUsername() {
- return username;
- }
- public void setUsername(String username)
- {
- this.username = username;
- }
- public int getUserage() {
- return userage;
- }
- public void setUserage(int userage) {
- this.userage = userage;
- }
- }
- public class GetField {
- public static void main(String[] args)throws Exception {
- Class clazz = Users.class;
- Field[] fields = clazz.getFields();
- for(Field f:fields){
- System.out.println(f);
- System.out.println(f.getName());
- }
- System.out.println("------------------------");
- Field[] fields2 =clazz.getDeclaredFields();
- for(Field f:fields2){
- System.out.println(f);
- System.out.println(f.getName());
- }
- System.out.println("------------------------");
- Field field = clazz.getField("userage");
- System.out.println(field);
- System.out.println("---------------------");
- Field field1 = clazz.getDeclaredField("username");
- System.out.println(field1);
- }
- }
- public class GetField2 {
- public static void main(String[] args)throws Exception {
- Class clazz = Users.class;
- Field field = clazz.getField("userage");
- //对象实例化
- Object obj = clazz.newInstance();
- //为成员变量赋予新的值
- field.set(obj,18);
- //获取成员变量的值
- Object o = field.get(obj);
- System.out.println(o);
- }
- }
修改Users类
- public class Users {
- private String username;
- public int userage;
- public Users(){ }
- public Users(String username,int userage){
- this.username= username;
- this.userage=userage;
- }
- public Users(String username){
- this.username= username;
- }
- private Users(int userage){
- this.userage = userage;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username)
- {
- this.username = username;
- }
- public int getUserage() {
- return userage;
- }
- public void setUserage(int userage) {
- this.userage = userage;
- }
- private void suibian(){
- System.out.println("Hello Oldlu");
- }
- }
- public class GetMethod {
- public static void main(String[] args)throws Exception{
- Class clazz = Users.class;
- Method[] methods = clazz.getMethods();
- for(Method m: methods){
- System.out.println(m);
- System.out.println(m.getName());
- }
- System.out.println("---------------------------");
- Method[] methods2 = clazz.getDeclaredMethods();
- for(Method m: methods2){
- System.out.println(m);
- System.out.println(m.getName());
- }
- System.out.println("--------------------------");
- Method method = clazz.getMethod("setUserage", int.class);
- System.out.println(method.getName());
- System.out.println("--------------------------");
- Method method1 = clazz.getDeclaredMethod("suibian");
- System.out.println(method1.getName());
- }
- }
- public class GetMethod2 {
- public static void main(String[] args)throws Exception {
- Class clazz = Users.class;
- Method method = clazz.getMethod("setUsername",String.class);
- //实例化对象
- Object obj = clazz.getConstructor(null).newInstance();
- //通过setUserName赋值
- method.invoke(obj,"oldlu");
- //通过getUserName获取值
- Method method1 = clazz.getMethod("getUsername");
- Object value = method1.invoke(obj);
- System.out.println(value);
- }
- }
- public class GetClassInfo {
- public static void main(String[] args) {
- Class clazz = Users.class;
- //获取类名
- String className = clazz.getName();
- System.out.println(className);
- //获取包名
- Package p = clazz.getPackage();
- System.out.println(p.getName());
- //获取超类
- Class superClass = clazz.getSuperclass();
- System.out.println(superClass.getName());
- //获取该类实现的所有接口
- Class[] interfaces = clazz.getInterfaces();
- for(Class inter:interfaces){
- System.out.println(inter.getName());
- }
- }
- }
需求:根据给定的方法名顺序来决定方法的执行顺序。
- class Reflect {
- public void method1(){
- System.out.println("Method1.......");
- }
- public void method2(){
- System.out.println("Method2.......");
- }
- public void method3(){
- System.out.println("Method3.......");
- }
- }
- public class ReflectDemo {
- public static void main(String[] args)throws Exception {
- Reflect rd = new Reflect();
- if(args != null && args.length > 0){
- //获取ReflectDemo的Class对象
- Class clazz = rd.getClass();
- //通过反射获取ReflectDemo下的所有方法
- Method[] methods = clazz.getMethods();
- for(String str :args){
- for(int i=0;i<methods.length;i++){ if(str.equalsIgnoreCase(methods[i].getName())){
- methods[i].invoke(rd);
- break;
- }
- }
- }
- }else{
- rd.method1();
- rd.method2();
- rd.method3();
- }
- }
- }
由于Java反射是要解析字节码,将内存中的对象进行解析,包括了 一些动态类型,而JVM无法对这些代码进行优化。因此,反射操作 的效率要比那些非反射操作低得多! 接下来我们做个简单的测试来直接感受一下反射的效率。
- public class Test{
- public static void main(String[] args) {
- try {
- //反射耗时
- Class clazz = Class.forName("com.bjsxt.Users");
- Users users = (Users) clazz.getConstructor(null).newInstance();
- long reflectStart = System.currentTimeMillis();
- Method method = clazz.getMethod("setUsername", String.class);
- for(int i=0;i<100000000;i++){
- method.invoke(users,"oldlu");
- }
- long reflectEnd = System.currentTimeMillis();
- //非反射方式的耗时
- long start = System.currentTimeMillis();
- Users u = new Users();
- for(int i=0;i<100000000;i++){
- u.setUsername("oldlu");
- }
- long end = System.currentTimeMillis();
- System.out.println("反射执行时 间:"+(reflectEnd - reflectStart)); System.out.println("普通方式执行时间:"+(end - start));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
setAccessible()方法: setAccessible是启用和禁用访问安全检查的开关。值为 true 则指示 反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指 示反射的对象应该实施 Java 语言访问检查;默认值为false。 由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关 闭安全检查就可以达到提升反射速度的目的。
- public class Test2 {
- public static void main(String[] args)throws Exception {
- Users users = new Users();
- Class clazz = users.getClass();
- Field field = clazz.getDeclaredField("username");
- //忽略安全检查
- field.setAccessible(true);
- field.set(users,"oldlu");
- Object object = field.get(users); System.out.println(object);
- System.out.println("-----------------------------");
- Method method = clazz.getDeclaredMethod("suibian");
- method.setAccessible(true);
- method.invoke(users);
- }
- }
Java 反射机制是Java语言一个很重要的特性,它使得Java具有了 “动态性”。
反射机制的优点:
1、更灵活。
2、更开放。
反射机制的缺点:
1、降低程序执行的效率。
2、增加代码维护的困难。
获取Class类的对象的三种方式:
1、运用getClass()。
2、运用.class 语法。
3、运用Class.forName()(最常被使用)。
反射机制的常见操作
1、动态加载类、动态获取类的信息(属性、方法、构造器)。
2、动态构造对象。
3、动态调用类和对象的任意方法。
4、动态调用和处理属性。
5、 获取泛型信息。
6、处理注解。