Java中的反射机制

反射(Reflect)是Java中可以解剖类的机制,通过反射我们可以获取包括访问权限为private在内的成员方法、成员变量、构造方法、并使用。

Java提供的这个功能提高了程序的动态性。

这里编写一个Car类,并添加不同参数,不同访问权限的构造方法、成员变量、成员方法,以演示反射机制的使用方法。

Car类:

public class Car {
    
    public String name;
    
    private int speed;
    
    private Car(){
        this.name = "概念车";
        this.speed = 150;
    }
    
    public Car(String name,int speed) {
        this.name = name;
        this.speed = speed;
    }
    
    public void horn(int times) {
        for(int i =0;i<times;i++) {
            System.out.print(name+" ");
            System.out.print("Beep!");
        }
        System.out.println();
    }
    private void run() {
        
        System.out.println(name + " is Running at a speed of "+speed);
    }

  public String toString() {
    return "汽车品牌为:" + name + ", 最高时速为:" + speed;
  }


}

获取类的字节码文件对象:

方式一:类名.class

Class c = Car.class;

方式二:对象.getClass()

Car ford = new Car("ford",60);
Class c = ford.getClass();

方式三:Class.forName(类的全名)

Class c = Class.forName("practice.Car");

注意方式三必须写上包名

获取public构造方法并使用:

Constructor cstr = c.getConstructor(String.class,int.class);
        
Object obj = cstr.newInstance("Ford",100);

获取private构造方法并使用:

Constructor<Car> cstr = c.getDeclaredConstructor();
        
Object obj = cstr.newInstance();
        
Car car = (Car)obj;
        
car.horn(3);

目前由于无参构造方法是私有的,所以运行会报错:

class practice.Main cannot access a member of class practice.Car with modifiers "private"

这是需要进行暴力反射

cstr.setAccessible(true);

获取public成员变量:

这里思考一下,获取字节码文件中的成员变量是获得变量对象,而如果想取值存值,必须要和具体的实例对象联系起来才有意义。

      Class<Car> c = Car.class;
        
        Field namefield = c.getField("name");
        

        Car ford = new Car("frod",130);
        System.out.println(ford);
        //汽车品牌为:frod, 最高时速为:130
        namefield.set(ford, "ford");
        
        System.out.println(ford);
        //汽车品牌为:ford, 最高时速为:130

获取private成员变量:

与上方类似,还是需要暴力反射才能操作private修饰的成员变量

        Class<Car> c = Car.class;
        
        Field speedField = c.getDeclaredField("speed");
        
        speedField.setAccessible(true);
        
        Car bmw = new Car("bmw",1);
        
        System.out.println(bmw);
        //汽车品牌为:bmw, 最高时速为:1
        
        speedField.set(bmw, 100);
        
        System.out.println(bmw);
        //汽车品牌为:bmw, 最高时速为:100

获取public成员方法:

这里需要注意int类型的形参,反射时要传递int.class而不是Integer.class

     Class<Car> c = Car.class;
        
        Method horn = c.getMethod("horn", int.class);
        
        Car audi = new Car("audi",123);
        
        horn.invoke(audi, 3);
        //audi Beep!audi Beep!audi Beep!

获取private成员方法:

    Class<Car> c = Car.class;
        
        Method run = c.getDeclaredMethod("run");
        
        run.setAccessible(true);
        
        Car skoda = new Car("skoda",116);
        
        run.invoke(skoda);
        //skoda is Running at a speed of 116

 

posted @ 2021-03-03 20:18  lucascube  阅读(76)  评论(0)    收藏  举报