1.1 什么是反射
程序运行期间,使用另外一种技术来创建对象实例,调用方法,后期我们经常使用,但很少去写【框架】

1.2 字节码对象
获取字节码对象

// 对象实例.getClass()
// 类.class
// Class.forName("全限定类名")
代码片段

// Class.forName("全限定类名");
@Test
public void test03() throws Exception {

Class c1 = Class.forName("com.itheima.b_reflect.b1_class.Student");
System.out.println(c1);

}
常用方法

public String getSimpleName(); 获取字节码简单名称 类名
public String getName(); 获取字节码全限定类名 包名+类名
public T newInstance(); 创建对象实例 要求:空参构造方法
代码片段

@Test
public void test03() throws Exception {

// 创建Student对象实例
Student o = (Student) clazz.newInstance();
System.out.println(o);

}
1.3 构造器
通过字节码对象获取构造器

public Constructor[] getConstructors(); 获取所有public修饰的构造器
public Constructor [] getDeclaredConstructors(); 获取所有声明的构造器

public Constructor getConstructor(Class.. 类型列表); 获取指定public修饰的构造器

public Constructor getDeclaredConstructor(Class.. 类型列表); 获取指定声明的构造器
常用方法

public T newInstance(Object... 参数列表); 创建对象实例
public void setAccessible(boolean true); 暴力反射
代码片段

// 获取private修饰的二个参数构造器
@Test
public void test05() throws Exception {

// 字节码对象
Class clazz = Class.forName("com.itheima.b_reflect.b2_constructor.Student");
// 构造器
// 错误 java.lang.NoSuchMethodException
// Constructor constructor = clazz.getConstructor(int.class, String.class);
Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class);
// java.lang.IllegalAccessException
constructor.setAccessible(true); // 取消全限检查 (暴力反射)
// 创建对象实例
Object o = constructor.newInstance(3, "林允");
System.out.println(o);

}
1.4 方法
通过字节码对象获取方法

public Method[] getMethods(); 获取所有public修饰的方法,包括父类的
public Method[] getDeclaredMethods();获取所有声明的方法,不包括父类

public Method getMethod(String 方法名,Class... 类型列表); 获取指定public修饰的方法

public Method getDeclaredMethod(String 方法名,Class... 类型列表); 获取指定声明的方法
常用方法

public T invoke(Object 对象实例,Object... 参数列表); 调用对象实例方法

public void setAccessible(boolean true); 取消全限检查(暴力反射)
代码片段

// private修饰的 sleep方法 有返回值
@Test
public void test05() throws Exception {

// 字节码对象
Class clazz = Class.forName("com.itheima.b_reflect.b3_method.Student");
// 方法
// 错误 java.lang.NoSuchMethodException
// Method method = clazz.getMethod("sleep");
Method method = clazz.getDeclaredMethod("sleep");
// 创建对象实例
Object o = clazz.newInstance();
// java.lang.IllegalAccessException
method.setAccessible(true);// 取消全限检查 (暴力反射)
// 调用
Object result = method.invoke(o);
System.out.println(result);

}

// public修饰的 静态 study 方法
@Test
public void test06() throws Exception {

// 字节码对象
Class clazz = Class.forName("com.itheima.b_reflect.b3_method.Student");
// 方法
Method method = clazz.getMethod("study");
// 调用方法
method.invoke(null);

}
1.5 属性【字段】
因为我们定义的属性,都提供了 setXxx getXxx 方法

通过字节码对象获取字段

public Field[] getFields(); 获取所有public修饰的字段
public Field[] getDeclaredFields(); 获取所有声明的字段
public Field getField(String 字段名); 获取指定public修饰字段
public Field getDeclaredField(String 字段名); 获取指定声明的字段
常用方法

public void set(Object 对象实例,Object 实参内容); 对象实例赋值
setInt setDouble
public T get(Object 对象实例); 对象实例取值
getInt getDouble
public Class getType(); 当前字段的类型
public void setAccessible(boolean true); 暴力反射
代码片段

// 给 name字段 赋值 取值 并判类型
@Test
public void test() throws Exception {

// 字节码对象
Class clazz = Class.forName("com.itheima.b_reflect.b4_field.Student");
// 获取name字段
// Field field = clazz.getField("name");
Field field = clazz.getDeclaredField("name");
// 创建对象实例
Object o = clazz.newInstance();
// 暴力反射
field.setAccessible(true);
// 赋值
field.set(o, "舒淇");
// 取值
field.get(o);
System.out.println(o);
// 字段类型
Class<?> type = field.getType();
System.out.println(type);

}
1.6 反射案例
spring 容器 (创建对象实例、存储对象实例)

需求

编写一个工厂方法,根据配置文件的信息生产任意对象实例

需求分析

编写一个Student类(编号、姓名、性别) 编写一个配置文件(类的信息 全限定类名 属性和对应的值)编写一个工厂方法 加载配置文件 生产对象

步骤分析

1 编写一个Student类(编号、姓名、性别)

2 编写一个配置文件(类的信息 全限定类名 属性和对应的值)

3 编写一个工厂方法 加载配置文件 生产对象

// 读取配置文件信息

// 创建字节码对象

// 创建对象实例

// 根据其他的属性信息 给对象实例赋值

@Test

public void test() throws Exception {

    // 创建properties对象
    Properties pro = new Properties();
    // 加载
    pro.load(new FileReader("student.properties"));

    // 获取配置文件的信息
    String className = pro.getProperty("className");
    String id = pro.getProperty("id");
    String name = pro.getProperty("name");
    String gender = pro.getProperty("gender");

    // 创建字节码对象
    Class clazz = Class.forName(className);

    // 获取public类型的带参构造方法
    Constructor constructor = clazz.getConstructor(int.class, String.class, String.class);

    // 创建对象实例,赋值
    Object o = constructor.newInstance(Integer.parseInt(id), name, gender);
    System.out.println(o);
  
    // 方法二
    // 读取配置文件信息
    InputStream is = TestRef.class.getClassLoader().getResourceAsStream("fun/chenqi/day01/demo01/student.properties");
    Properties properties = new Properties();
    properties.load(is);
    // 创建字节码对象
    Class clazz = Class.forName(properties.getProperty("className"));
    // 创建对象实例
    Object o = clazz.newInstance();
    // 根据其他的属性信息 给对象实例赋值
    Set<String> keys = properties.stringPropertyNames();
    // 遍历key
    for (String key : keys) {
        // 处理 className  跳出本次循环
        if ("className".equalsIgnoreCase(key)) continue;
        // 获取 value
        String value = properties.getProperty(key);
        // 获取field   id name gender
        Field field = clazz.getDeclaredField(key);

        field.setAccessible(true);// 暴力反射
        // 获取当前的字段类型
        Class<?> type = field.getType();
        if (type == int.class) {
            field.setInt(o, Integer.parseInt(value));
        } else {
            // 赋值操作
            field.set(o, value);
        }

    }
    System.out.println(o);
最后修改:2019 年 07 月 29 日 05 : 33 PM