Java反射机制

JAVA反射机制是在运行状态中,动态获取的类的所有信息以及动态调用对象的方法(或属性),称为java语言的反射机制。

注意:反射是在运行的时候进行的,不是在编译的时候运行的。

反射的功能

Java反射机制主要提供了以下功能

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;生成动态代理。

API简介

在这里先看一下sun为我们提供了那些反射机制中的类:

  — java.lang.Class;        代表一个类

  — java.lang.reflect.Constructor; 代表类的构造方法 

  — java.lang.reflect.Field;        代表类的成员变量(成员变量也称为类的属性)

  — java.lang.reflect.Method;  代表类的方法

  — java.lang.reflect.Array;  提供了动态创建数组,以及访问数组的元素的静态方法

注意:java中无论生成某个类的多少对象, 这些对象都会对应于同一个Class对象。

方法介绍

方法关键字 含义
getDeclaredMethods() 获取所有的方法
getReturnType() 获得方法的放回类型
getParameterTypes() 获得方法的传入参数类型
getDeclaredMethod("方法名",参数类型.class,……) 获得特定的方法
   
构造方法关键字 含义
getDeclaredConstructors() 获取所有的构造方法
getDeclaredConstructor(参数类型.class,……) 获取特定的构造方法
   
父类和父接口 含义
getSuperclass() 获取某类的父类
getInterfaces() 获取某类实现的接口

获取Class的三种方式

1)使用Class类的forName(String className)静态方法。改方法需要传入字符串参数,改字符串参数的值是某个类的全限定类名(必须添加完整的包名)。

Class.forName("java.lang.String");

2)调用某个的class属性来获取该类对应的class对象,如

String.class

3)调用某个对象的getClass方法。

String s = "aa";
Class<?> clazz = s.getClass();

生成对象

1)通过不带参数的构造方法生成对象有两种方法

  a)先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:

  newInstance()方法可以返回一个实例,但是构造方法要是没有参数列表的,它相当于调用某个类的不带参数的构造方法,但是如果在初始化对象的时候要传参数,就要使用Constructor

Class<?> classType = String.class;
Object obj = classType.newInstance(); 

  b)先获得Class对象,然后通过该对象获得相应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:

Class<?> classType = object.getClass();
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});

2)若想通过类的带参数的构造方法生成对象,只能使用下面一种方式

   Class<?> classType = object.getClass();
   Constructor cons = classType.getConstructor(new Class[]{String.class,int.class});
   Object obj = cons.newInstance(new Object[]{"hello",3});
   //以上的两行代码等价于下面一行
   //Object obj2 = classType.newInstance();

反射访问私有(private)的方法

  private 限制的方法没有办法在另外的类中使用,但可以使用反射进行使用。而getMethod()方法只能获取public的方法。如果要使用private的方法就要使用 getDeclaredMethod()方法。

1、获取privete方法

复制代码
public class PrivateTest {
    private String sayHello(String name){
      return "hello" + name;
   }
}
public class Test{
  public static void main(String[] args) throws Exception{

    PrivateTest obj = new PrivateTest();
    Class<?> classType = obj.getClass();
    Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class});
    method.setAccessible(true);       //压制java的访问控制检查
    String str = (String)method.invoke(obj, new Object[]{"aaa"});

  }
}
复制代码

2、改变private的属性

复制代码
public class PrivateTest2 {
   private String name = "张三";
   public String getName(){
      return name;
   }
}
public class Test{
   public static void main(String[] args) throws Exception{

    PrivateTest2 obj = new PrivateTest2();
    Class<?> classType = obj.getClass();
    Field field = classType.getDeclaredField("name");
    field.setAccessible(true);
    field.set(obj, "李四");
    System.out.println(obj.getName());
   }
}
复制代码

 反射机制的优点与缺点

为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。

  • 静态编译:在编译时确定类型,绑定对象,即通过。
  • 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。  

  优点——可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中。

  比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。

  缺点——对性能有影响。

  使用反射基本上是一种解释操作,这类操作总是慢于只直接执行相同的操作。

原文地址:https://www.cnblogs.com/bingo1717/p/7746123.html