反射

65 阅读3分钟

反射

入门

获取Class对象的三种方法

  • 第一种:使用Class的静态方法forName()
  • 第二种:使用类名.class
  • 第三种:使用实例的getClass()方法 [示例代码]
//获取Class对象的方法一:通过Class.froName()方法获取,参数为类的全包名
Class<?> aClass1 = Class.forName("com.zssd.entity.Student");
//获取Class对象的方法二:通过类名.class获取
Class<Student> aClass2 = Student.class;
//获取Class对象的方法三:使用实例对象的getClass()方法
Student student = new Student();
Class<? extends Student> aClass3 = student.getClass();

实例化对象

  • 通过newInstance方法实例化对象
  • 通过构造器实例化对象 [示例代码]
//获取Class对象的方法一:通过Class.froName()方法获取,参数为类的全包名
Class<?> aClass = Class.forName("com.zssd.entity.Student");
//通过newInstance方法实例化对象
Object o = aClass.newInstance();
//获取无参构造器,通过构造器的newInstance()方法实例化对象
Constructor<?> constructor = aClass.getConstructor();
Object o1 = constructor.newInstance();

反射获取类的构造器

  • 获取指定参数类型的公共构造方法(公共的):getConstructor(Class<?>... parameterTypes)
  • 获取指定参数类型的构造方法:getDeclaredConstructor(Class<?>... parameterTypes)
  • 获取所有构造方法(公共的):getConstructors()
  • 获取所有的构造方法:getDeclaredConstructors() [示例代码]
//获取Class对象的方法一:通过Class.froName()方法获取,参数为类的全包名
Class<?> aClass = Class.forName("com.zssd.entity.Student");
//获取指定参数类型的公共构造方法,无参以及有参
Constructor<?> constructor1 = aClass.getConstructor();
Constructor<?> constructor2 = aClass.getConstructor(String.class,Integer.class,String.class);
//获取所有公共的构造方法
Constructor<?>[] constructors = aClass.getConstructors();
//获取指定参数类型的构造方法,无参以及有参
Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor();
Constructor<?> declaredConstructor2 = aClass.getDeclaredConstructor(String.class,Integer.class,String.class);
//获取所有的构造方法
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();

反射获取类的成员变量

  • 获取指定的成员变量(公共的):getField(String name)
  • 获取指定的成员变量:getDeclaredField(String name)
  • 获取所有的成员变量(公共的):getFields()
  • 获取指定的成员变量:getDeclaredFields() [示例代码]
//获取Class对象的方法一:通过Class.froName()方法获取,参数为类的全包名
Class<?> aClass = Class.forName("com.zssd.entity.Student");
//获取指定的成员变量(公共的)
Field field = aClass.getField("name");
//获取指定的成员变量
Field declaredField = aClass.getDeclaredField("name");
//获取所有的成员变量(公共的)
Field[] fields = aClass.getFields();
//获取所有的成员变量
Field[] declaredFields = aClass.getDeclaredFields();

反射获取类的方法

  • 获取指定的方法(公共的):getMethod(String methodName,Class<?>... parameterTypes)
  • 获取指定的方法:getDeclaredMethod(String methodName,Class<?>... parameterTypes)
  • 获取所有方法(公共的,包含继承父类的方法):getMethods()
  • 获取所有的方法(不包含继承父类的):getDeclaredMethods() [示例代码]
//获取Class对象的方法一:通过Class.froName()方法获取,参数为类的全包名
Class<?> aClass = Class.forName("com.zssd.entity.Student");
//获取指定方法名的方法(公共的)
Method getName = aClass.getMethod("getName");
//获取指定方法名的方法
Method setName = aClass.getDeclaredMethod("setName", String.class);
//获取所有方法(公共的,包含继承父类的方法)
Method[] methods = aClass.getMethods();
//获取所有方法(不包含父类的方法)
Method[] declaredMethods = aClass.getDeclaredMethods();

属性赋值以及invoke()方法

[示例代码]

Field age = aClass.getDeclaredField("age");
age.setAccessible(true);
age.set(student, 20);

[示例代码]

Method setName = aClass.getMethod("setName", String.class);
setName.invoke(student, "李四");

说明:如果属性或者方法是私有的话,要想赋值或者传参成功,需要执行age.setAccessible(true).表示允许访问(谨慎使用)

反射的一些应用以及问题

  • 应用:JDBC数据库的链接,java框架的使用

  • 问题:

    • 性能问题:java反射的性能并不好,因为主要是编译器没法对反射相关的代码做优化
    • 安全问题:反射可以修改访问权限,使用反射的话通常需要程序的运行没有安全限制