java反射机制

1、概述

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

可以理解为对类的解剖。

2、获取Class类的对象的三种方式

(1)、Object类中的getClass()方法

Person p = new Person();
Class pc = p.getClass();

(2)、通过静态属性class

Class pc = Person.class;

(3)、通过Class类中的forName方法

String className = "src/reflect/Person";//带包的路径
Class pc = Class.forName(className);

3、获取Class中的构造函数

class Person {
    public String name;
    private int age;
    Person() {

    }
    Person(int age, String name) {
        this.name = name;
        this.age = age;
    }
}

//字节码文件对象,class对象的类
Class pc = Class.forName(className);

//生成该字节码文件对象,class对象,调用的是空参的构造函数
Object obj = pc.newInstance();

//实参的构造函数,生成对象,先获取构造函数
Constructor ct = pc.getConstructor(int.class,String.class);

//通过构造器对象的newInstance方法生成对象
Object obj = ct.newInstance(38,"小明");

4、获取Class中的字段

//字节码文件对象,class对象的类
Class pc = Class.forName(className);

//只能获取public字段
Field nameField = pc.getField("name");

//能获取public和private字段
Field ageField = pc.getDeclaredField("age");

//对私有字段的访问取消权限检查,暴力访问
ageField.setAccessible(true);

//生成对象
Object obj = pc.newInstance();

//age赋值
ageField.set(obj,22);

//age取值
Object ageValue = field.get(obj);

syso(ageValue);//22

5、获取Class中的方法

//字节码文件对象,class对象的类
Class pc = Class.forName(className);

//获取所有的public方法,包含父类中的
Method[] methods = pc.getMethods();

//获取本类中所有的public和private方法,不包含父类中的
methods = pc.getDeclaredMethods();

//获取指定的空参方法show,null代表空参
Method showMethod = pc.getMethod("show",null);

//生成对象
Object obj = pc.newInstance();

//调用show方法,null代表实参
showMethod.invoke(obj,null);

//获取指定的带参数的方法paramMethod
Method paramMethod = pc.getMethod("paramMethod", String.class, int.class);

//调用paramMethod方法
paramMethod.invoke(obj,"小强",22);

6、反射练习

public class ReflectPractice {
    public static void main(String[] args) throws IOException, ReflectiveOperationException {
        //主板开启
        Mainboard mb = new Mainboard();
        mb.run();

        //加载声卡,网卡等设备
        //读取配置文件,获取设备类名称
        File configFile = new File("pci.properties");
        if(!configFile.exists())
            configFile.createNewFile();
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream(configFile);
        prop.load(fis);
        for(int x=0; x<prop.size(); x++) {
            String pciName = prop.getProperty("pci"+(x+1));
            //根据设备名,获取该设备字节码文件对象
            Class clazz = Class.forName(pciName);
            //实例化设备对象
            PCI p = (PCI)clazz.newInstance();
            //运行设备
            mb.usePCI(p);
        }
        fis.close();
    }
}

public interface PCI {
    public void open();
    public void close();
}    

public class Mainboard {

    public void run() {
        System.out.println("mainboard run");
    }

    public void usePCI(PCI p) {
        if(p != null) {            
            p.open();
            p.close();
        }
    }

}

public class NetCard implements PCI {

    @Override
    public void open() {
        System.out.println("netcard open");
    }

    @Override
    public void close() {
        System.out.println("netcard close");
    }

}

public class SoundCard implements PCI{

    @Override
    public void open() {
        System.out.println("sound open");
    }

    @Override
    public void close() {
        System.out.println("sound close");
    }

}

file pci.properties

pci1=reflect.SoundCard
pci2=reflect.NetCard

只需要向配置文件中添加设备名称即可,不用再修改mainborad文件,增加了程序的扩展性。