1.概述

反射是框架设计的灵魂

框架:半成品软件,可以在框架的基础上进行软件开发,简化代码

反射:将类的各个组成部分封装为其他对象,这就是反射机制

反射(Reflection)_加载

反射(Reflection)_加载_02

通过new创建实例和反射创建实例,都绕不开Class对象

 好处:

  •   在程序的运行过程中,去操作这些对象
  •   可以解耦,提高程序的可扩展性

2.获取字节码Class对象的三种方法

  (1)class.forName("全类名"):将字节码文件加载进内存,返回class对象。多用于配置文件,将类名定义在配置文件中,读取文件,加载类

  (2)类名.class:通过类名的属性class获取。多用于参数的传递

  (3)对象.getClass():getClass()方法在Object类中定义着。多用于对象获取字节码的方式。

  结论

    同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个。

反射(Reflection)_java_03

 反射(Reflection)_加载_04

Person .java
package domain;

public class Person {
    String name;
    int age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

  ReflectDemo1.java

package reflect;

import domain.Person;

public class ReflectDemo1 {
    /**
     * 获取class对象的三种方式
     */
    public static void main(String[] args) throws Exception {
        // 1. Class.forName("全类名")
        Class<?> aClass = Class.forName("domain.Person");
        System.out.println(aClass);

        // 2.类名.class
        Class<Person> personClass = Person.class;
        System.out.println(personClass);

        // 3.对象.getClass()
        Person person = new Person();
        Class<? extends Person> aClass1 = person.getClass();
        System.out.println(aClass1);

        // 用== 比较三个对象引用的在内存中的地址,如果地址值相同,说明这三个引用指的是堆内存中同一个对象
        System.out.println(aClass == personClass);  // true
        System.out.println(aClass == aClass1);      // true
    }
}

  运行结果:

反射(Reflection)_字节码_05

 每一个字节码文件对应的class对象都不同

反射(Reflection)_加载_06

 3.class对象的功能

 (1)获取功能

  • 获取成员变量们

        Field[] getFields()    获取所有public修饰的成员变量

     Field getField(String name)   获取指定名称的public修饰的成员变量

 

     Field[] getDeclareFields()  获取所有的成员变量,不考虑修饰符

     Field getDeclareField()

  • 获取构造方法们

     Constructor<?>[] getConstructors()

    Constructor<T> getConstructor(类<?>... parameterTypes)  

 

    Constructor<?>[] getDeclaredConstructors()

    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  

  • 获取成员方法们

    方法[] getMethods()

     方法 getMethod(String name, 类<?>... parameterTypes)  

    

    方法[] getDeclaredMethods()

     方法 getDeclaredMethod(String name, 类<?>... parameterTypes)  

  • 获取类名

     String getName()  

 (2)Field:成员变量

  操作:

    设置值:

      void set(Object obj, Object value)

    获取值:

      get(Object obj)

    忽略访问权限修饰符的安全检查

      setAccessible(true); 暴力反射

反射(Reflection)_成员变量_07

反射(Reflection)_成员变量_08

 运行结果:

反射(Reflection)_加载_09

 反射(Reflection)_字节码_10

 运行结果:

反射(Reflection)_java_11

 (3)Constructor:构造方法

   创建对象:

    T newInstance(Object...initargs)

import java.lang.reflect.Constructor;

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        // 获取Person的Class对象
        Class<Person> personClass = Person.class;
        // Constructor<T> getConstructor(类<?>...parameterTypes)
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);

        // 构造器创建对象
        Person person = constructor.newInstance("张三", 23);
        System.out.println(person);

        System.out.println("=====================");

        // 使用空参构造
        Constructor<Person> constructor1 = personClass.getConstructor();
        System.out.println(constructor1);

        // 使用空参构造器创建对象
        Person person1 = constructor1.newInstance();
        System.out.println(person1);
        
    }
}

  运行结果:

反射(Reflection)_加载_12

 

 (4)Method:方法对象

Person.java

package cn.yjg.day10.demo07;

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

    public String a;
    protected String b;
    String c;
    private String d;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }

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

    public void eat(String food){
        System.out.println("eat..." + food);
    }
}

  

package cn.yjg.day10.demo07;

import java.lang.reflect.Method;

public class ReflectDemo4 {
    public static void main(String[] args) throws Exception {
        // 获取Person的Class对象
        Class<Person> personClass = Person.class;
        // 获取指定名称的方法对象
        Method eat_method = personClass.getMethod("eat");
        Person p = new Person();
        // 执行方法
        eat_method.invoke(p);

        // 有参的成员方法
        Method eat_method2 = personClass.getMethod("eat", String.class);
        eat_method2.invoke(p, "饭");

        System.out.println("------------------");
        // 获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method: methods) {
            System.out.println(method);
        }
    }
}

  运行结果:

反射(Reflection)_加载_13

 (5)获取方法名

反射(Reflection)_类名_14

 运行结果:

反射(Reflection)_java_15

 (6)获取类名

反射(Reflection)_加载_16

 运行结果:

反射(Reflection)_字节码_17

 

 

 参考:学习java应该如何理解反射?