Java反射技术

什么是反射?

  Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称为反射机制。

  所谓反射其实是获取类的字节码文件,也就是.class文件,那么我们可以通过Class类的对象进行获取。

  其实这个知识点在Java基础学习中已经有所涉及,知识没有深入开展讲解。比如加载数据库JDBC驱动时Class.forName("com.mysql.jdbc.Driver")

关于Class类

  Class类的实例表示正在运行的Java应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象(包括基本数据类型)

  Class类没有公共构造方法。Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

  注意在运行期间,一个类只有一个Class对象产生。

 

下面我们通过创建一个实体类Fruit来感受一下Java的反射机制。

public class Fruit {
    private String name;
    private Double price;

    public Fruit() {
    }

    public Fruit(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Fruit{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    public String print(){
        return "The price of "+name+" is "+price+" yuan.";
    }
}

 

反射的三种方式

  1. 第一种方式:
    Object——>getClass(),因为Object类中存在getClass()方法,而所有类都继承了Object类,所以可以调用Object类来获取。

    Fruit fruit = new Fruit();
    Class fruitclass1 = fruit.getClass();  
    System.out.println(fruitclass1);

    但是第一种方式下,对象都有了还要什么反射,所以几乎不用该方法。

  2. 第二种方式:
    任何数据类型(包括基本数据类型)都有一个“静态”的class属性,我们可以据此获得。

    Class fruitclass2 = Fruit.class;
    System.out.println(fruitclass2);

    第二种方式需要导入类的包,依赖性太强,所以该方法用得不多。

  3. 第三种方式:

    通过Class类的静态方法forName(String className)。
    Class fruitclass3 = Class.forName("Fruit");
    System.out.println(fruitclass3);
    一般我们使用第三种方式,一个字符串可以传入也通过配置文件导入。

反射的使用

  1. 获取构造方法

    1. 批量的方法

      Constructor[] cons = fruitclass.getConstructors();           //获取所有“公有的”构造方法
      Constructor[] cons2 = fruitclass.getDeclaredConstructors();  //获取所有的构造方法,包括私有、受保护、默认、公有
      for(Constructor con:cons){
          System.out.println(con);
      }
      System.out.println("--------------------------");
      for(Constructor con2:cons2){
          System.out.println(con2);
      }
    2. 单个的方法

      Constructor c = fruitclass.getConstructor(String.class,Double.class);            //获取单个的“公有的”构造方法
      Constructor c2 = fruitclass.getDeclaredConstructor(String.class,Double.class);   //获取单个的构造方法,可以是私有、受保护、默认、公有
      Object obj = c.newInstance("Apple",5.5);
      Object obj2 = c2.newInstance("Orange",7.0);
      System.out.println(obj.toString());
      System.out.println(obj2.toString());
      newInstance是Constructor类的方法(管理构造函数的类),用来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化实例。
  2. 获取成员变量

    1. 批量的方法

      Field[] fields = fruitclass.getFields();            //获取所有“公有的”成员变量
      Field[] fields2 = fruitclass.getDeclaredFields();   //获取所有的成员变量(包括私有、受保护、默认、公有)
      for(Field field:fields2){
          System.out.println(field);
      }
    2. 单个的方法

      Field f = fruitclass.getDeclaredField("price");
      f.setAccessible(true);  //暴力反射,解除私有限定
      f.set(obj,6.2);         //修改实例obj成员变量price的值
      System.out.println(((Fruit)obj).getPrice());
  3. 获取成员方法

    1. 批量的方法

      Method[] methods = fruitclass.getMethods();             //获取所有"公有的"成员方法(包含了父类的方法也包含Object类)
      Method[] methods2 = fruitclass.getDeclaredMethods();    //获取所有的成员方法,包含私有的(不包括继承的)
      for (Method m : methods){
          System.out.println(m);
      }
      System.out.println("--------------------------");
      for (Method m : methods2){
          System.out.println(m);
      }
    2. 单个的方法

      Method m = fruitclass.getMethod("print",null);                       //获取单个“公有的”成员方法
      Method m2 = fruitclass.getDeclaredMethod("setPrice", Double.class);  //获取某个成员方法,可以是私有、受保护、默认、公有
      m.invoke(obj,null);
      m2.invoke(obj2,7.5);
      System.out.println(((Fruit)obj).print());
      System.out.println(((Fruit)obj2).print());
      invoke是Method类的一个方法,第一个参数是要调用方法的对象,后面参数是调用方法时所传递的实参
posted @ 2022-03-01 17:42  蜗牛也要往上爬  阅读(18)  评论(0编辑  收藏  举报