Java反射机制特点的总结


反射的概述

什么是Java反射机制

  • Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

Java反射机制示意图

Java反射机制的作用

  • 是用来编写一些通用性较高的代码或者框架的时候使用。

反射的API

反射常用对象的概述

  • Class

    • Class类的实例表示正在运行的Java应用程序中的类和接口。
  • Constructor

    • 关于类的单个构造方法的信息以及对它的访问权限。
  • Field

    • Field提供了有关类或者接口的单个字段的信息,以及对它的动态访问的权限。
  • Method

    • Method提供了关于类或者接口上单独某个方法的信息。

Java反射常用对象介绍图解

Class类

  • Java中java.lang.Class类用于表示一个类的字节码(.class)文件
  • 如何得到某个class文件对应的Class对象
//已知类和对象的情况下
类名.class
对象.getClass() //Object类提供
//未知类和对象的情况下
Class.forName("包名.类名")
  • Class类代表了某个类的字节码,并提供了加载字节码的方法:forName(“包名.类名”),forName方法用于加载类字节码到内存中,并封装成一个Class对象。如下代码是常用的一种反射示例代码。
//1. 通过类名.class
Class class1 = Person.class;
//2. 通过对象.getClass()的方式
Person person = new Person();
Class class2 = person.getClass();
//3. Class.forName() 这是更常用的方式
try {
    Class.forName("io.github.zbw0520.reflect.test.Person");
} catch (Exception e) {
    e.printStackTrace();
}

Constructor类

  • Constructor类的实例对象代表类的一个构造方法

  • 得到某个类所有的构造方法

    Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
    
  • 得到指定的构造方法并调用

Constructor Constructor = Class.forName("java.lang.String").getConstructor(String.class);
String str = (String)Constructor.newInstance("abc");
  • Class类的newInstance()方法用来调用类的默认构造方法
String obj = (String)Class.forName("java.lang.String").newInstance();
  • 下面为Constructor类使用的具体实例代码
@Test
/**
* 获得无参数构造方法
*/
public void demo1() throws Exception{
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    Constructor c = class1.getConstructor();
    Person person = (Person)c.newInstance();    //相当于Person person = new Person();
    person.eat();
}
@Test
/**
* 获得有参数的构造方法
*/
public void demo2() throws Exception{
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    Constructor c = class1.getConstructor(String.class,String.class);
    Person person = (Person)c.newInstance("张三","男");
    System.out.println(person.getName()+"  "+person.getGender());
}

Field类

  • Field类代表了某个类中的一个成员变量,并提供动态的访问权限

  • Field对象的获得

    • 得到所有的成员变量

      Field[] fields = c.getFields();//获取所有public属性(包括父类继承)
      Field[] fields = c.getDeclaredFields();  //取得所有申明的属性
      
    • 得到指定的成员变量

      Field name = c.getField("name");    //传入属性名称
      Field name = c.getDeclaredFields("name");   //经常使用这个函数,无论是私有还是公有都可以通过这个函数访问
      
  • 设置Field变量是否可以访问

    field.setAccessible(boolean);   //设置私有属性的访问权限是否为真
    
  • Field变量值的读取

    field.get(obj); //读取数据
    field.set(obj,value);   //设置数据
    
  • Field类使用代码示例

@Test
/**
    * 测试公有属性
    */
public void demo1() throws Exception {
    //获得Class
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    //获得属性
    Field name = class1.getField("name");
    //操作属性
    Person p = (Person)class1.newInstance();
    name.set(p,"小王");
    System.out.println(name.get(p));
}
@Test
/**
    * 测试私有属性
    */
public void demo2() throws Exception{
    //获得Class
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    //获得私有属性
    Field f = class1.getDeclaredField("gender");
    //操作属性
    Person p = (Person)class1.newInstance();
    //私有属性需要设置可访问权限
    f.setAccessible(true);
    f.set(p,"女");
    System.out.println(f.get(p));
}

Method类

  • Method类代表某个类中的一个成员方法

  • Method对象的获得

    • 获得所有方法

      getDeclaredMethods()
      getMethods
      
    • 获得指定的方法

      getDeclaredMethod(String name, Class<?>...parameterTypes)
      getMethod(String name, Class<?>...parameterTypes)
      
  • 通过反射执行方法

invoke(Object obj, Object...args)
  • Method类使用代码示例
@Test
/**
    * 测试公有方法
    */
public void demo1() throws Exception{
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    //实例化
    Person p = (Person)class1.newInstance();
    //获得公有方法
    Method mt = class1.getMethod("eat");
    //执行该方法
    mt.invoke(p);
}
@Test
/**
    * 测试私有方法
    */
public void demo2() throws Exception{
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    //实例化
    Person p = (Person)class1.newInstance();
    //获得私有方法
    Method mt = class1.getDeclaredMethod("run");
    //指定可访问性为真
    mt.setAccessible(true);
    //执行方法
    mt.invoke(p);
}
@Test
/**
    * 测试带参私有方法
    */
public void demo3() throws Exception{
    Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
    //实例化
    Person p = (Person)class1.newInstance();
    //获得私有方法
    Method mt = class1.getDeclaredMethod("greet",String.class);
    //指定可访问性为真
    mt.setAccessible(true);
    //执行方法
    mt.invoke(p,"小明");
}

文章作者: 南航古惑仔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 南航古惑仔 !
  目录