Bootstrap

反射的概念和使用

反射的概念

 反射是框架设计的灵魂,就是在类运行期间把类中成员抽取为其他类的过程

为什么使用反射

反射就是为了解决在运行期间对某个实例一无所知的情况下调用其方法和属性

获取class反射类的三种方式

一、通过类名.class属性
    Class<泛型> 命名 = 类名.class;
二、通过类路径获取
    Class 命名 = Class.forName("com.路径.精确到具体类名");
三、通过对象名获取反射类型
    类名 命名1 = new 类名();
	Class 命名 = 命名1.getClass();

Class类常用方法

public static void main(String[] args) throws Exception{
	Class<泛型> 命名1 = 类名.class;	
	//通过反射类创建类对象	newInstance()
    类名 命名 = 命名1.newInstance();
    //获取反射类的注解对象	getAnnotation()
    注解类名 命名 = 命名1.getAnnotation(注解类名.class);
    //获取类的名称	getSimpleName()
    命名1.getSimpleName()
}

获取Method方法类对象

public static void main(String[] args) throws Throwable(){
	Class<泛型> 命名1 = 类名.class;
    //得到本类中定义的所有Method类对象	getDeclaredMethods()
    Method[] 命名2 = 命名1.getDeclaredMethods();
    for(Method 命名 : 命名2){
        通过遍历获取每一个本类中定义的Method类对象
    }
    
     //获取本类中指定的方法对象	getDeclaredmethod()
    Method 命名 = 命名1.getDeclaredMethod("方法名", 参数类型.class);
   
    //获取本类和父类所有public方法对象	getMethods()
    Method[] 命名3= 命名1.getMethods();
    for(Method 命名 : 命名3){
        遍历获取本类和父类的每一个public方法
    }
    
    //获取本类和父类指定的public方法对象	getMethod()
    Method 命名 = 命名1.getMethod("方法名", 参数类型.class);
}

Method类对象中常用方法

public static void main(String[] args) throws Exception{
    //?表示泛型通配符||占位符
    Class<?> 命名1 = Class.forName("com.路径具体到类名");
    Object 命名2 = 命名1.newInstance();
    Method 命名3 = 命名1.getMethod('方法名');
    
    //执行方法,返回方法执行结果 invoke(Object对象, 参数值)
    Object 命名 = 命名3.invoke(命名2);

    //获取方法名
    命名3.getName();

    //获取方法上的注解
    命名3.getAnnotation(注解类名.class)
    
    //私有方法不能被反射调用 需要使用强力反射
   	Method 命名4 = 命名1.getDeclaredMethod("方法名");
    命名4.setAccessible(true);	//设置为允许访问
    Object 命名 = 命名4.invoke(命名2)
}

获取Field属性对象的方式

getDeclaredField(属性名) 获取本类指定的属性对象

getDeclaredFields() 获取本类所有的属性对象

getField(属性名) 获取本类和父类中指定的public修饰的属性

getFields() 本类和父类中所有public属性

public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
	Class<泛型> 命名1 = 类名.class;
	类名 命名= 命名1.newInstance();
    Field 命名 = 命名1.getDeclaredField("属性名");
}

Field类中常用方法

Class<泛型> 命名1 = 类名.class;
类名 命名2 = 命名1.newInstance();  //等价于===new 类名()
Field 命名3 = 命名1.getDeclaredField("属性名");
//为属性赋值,如果是私有属性同样需要强力反射设置允许访问	set(Object对象, 值)
命名3.set(命名2, "属性值");	//等价于===类名.set属性名("属性值")

//获取属性名
Field[] 命名4 = 命名1.getDeclaredFields();
for(Field 命名5 : 命名4){
    //获取属性名
    命名5.getName();
    //获取每个属性对象上的注解对象
    注解类名 命名 = 命名5.getAnnotation(注解类名.class);
}

示例

properties属性文件指定类路径,通过反射完成类对象创建和类中属性赋值

public static void main(String[] args) throws Exception{
    //加载属性文件
    InputStream 命名1 = 当前文件名.class.getClassLoader().getResourceAsStream("属性文件名.properties");
    //通过属性类Properties
    Properties 命名2 = new Properties();
    命名2.load(命名1);
    //属性类读取属性文件中指定key值
    String 命名3 = 命名2.getProperty("属性文件中属性名");
    //根据类路径得到反射对象
    Class<?> 命名4 = Class.forName(命名3);
    //根据反射类创建类对象
    Object 命名7 = 命名4.newInstance();
    //为属性赋值
    Field[] 命名5 = 命名4.getDeclaredFields();
    for(Field 命名6 : 命名5){
        命名6.setAccessible(true);
        field.set(命名7, 属性值);
    }
}

;