定义

反射是框架的灵魂,对于任意一个类,能够动态获取信息以及动态调用对象方法的功能,这被称为反射机制。



对象的创建

静态

比如Person p = new Person(),在编译时就已经确定了具体类型,绑定了对象



动态

运行时才会确定具体类型,能够有效降低类之间的耦合度,最大限度发挥java的灵活性



反射机制的实现

在java中,使用一个类,需要把这个类加载到虚拟机(内存)当中,并生成Class对象,这个对象保存了该类的所有信息。反射机制,就是获取这个Class对象。

使用反射的方法

//最常用的方式,多用于读取配置文件
Class p1 = Class.forName("com.person");
    
//通过类名来获取,但此方法会导入类包,具有依赖性;可用于参数传递
Class p2 = Person.class;

//通过已存在对象创建;可用于获取对象的字节码
Person p = new Person();
p.getClass();



使用反射机制

创建对象

  • 创建一个实体类
public class Person
{
    private int id;
    private String name;
    private int age;
    public String city;

    public Person()
    {
    }

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

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    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;
    }

    public String getCity()
    {
        return city;
    }

    public void setCity(String city)
    {
        this.city = city;
    }

    private void show(String arg)
    {
        System.out.println("--------------show--->" + arg + "-----------");
    }
    
    public void say()
    {
        System.out.println("-------------------------say-------------------------");
    }
}
  • 创建对象
//newInstance创建对象
//事实上,它利用实体类的无参构造方法创建对象,如果注释了无参构造,则会创建失败
@Test
public void newTemp1() throws Exception
{
    Class temp = Class.forName("com.model.Person");
    Object o = temp.newInstance();
    System.out.println(o);
}



//getConstructor创建对象
//可以利用有参构造进行对象的创建,但是类型需要对应,否则会报错
@Test
public void newTemp2() throws Exception
{
    Class temp = Class.forName("com.model.Person");
    //构造器对象,可以传入参数
    Constructor cons = temp.getConstructor(int.class, String.class, int.class);
    Object o = cons.newInstance(1, "aa", 12);
    System.out.println(o);
}



获取构造方法

Class temp = Class.forName("com.model.Person");

//获取所有public构造方法
Constructor[] cons1 = temp.getConstructors();
for (Constructor constructor : cons1)
{
    System.out.println("------------cons1" + constructor);
}

//获取所有构造方法(任意类型)
Constructor[] cons2 = temp.getDeclaredConstructors();
for (Constructor constructor : cons2)
{
    System.out.println("------------cons2" + constructor);
}

//获取单个public构造方法
Constructor con1 = temp.getConstructor();
System.out.println("------------con1" + con1);

//获取某个构造方法(任意类型)
Constructor con2 = temp.getDeclaredConstructor();
System.out.println("------------con2" + con2);



获取成员变量

Class temp = Class.forName("com.model.Person");

//单个获取
//获得某个public字段
Field city = temp.getField("city");

//获得某个字段(任意类型)
Field name = temp.getDeclaredField("name");

//批量获取
//获得所有public字段
Field[] fields = temp.getFields();
for (Field field : fields)
{
    System.out.println(field);
}

//获得所有字段(任意类型)
Field[] declaredFields = temp.getDeclaredFields();
for (Field declaredField : declaredFields)
{
    System.out.println(declaredField);
}



给对象赋值

//创建实例
Class temp = Class.forName("com.model.Person");
Object o = temp.newInstance();

//给public属性赋值
Field city = temp.getField("city");
city.set(o,"Toronto");

Person p = (Person) o;
System.out.println(p.getCity());


//给任意属性赋值
Field name = temp.getDeclaredField("name");
//解除私有限定
name.setAccessible(true);
name.set(o, "Sam");

System.out.println(p.getName());



获得方法

Class temp = Class.forName("com.model.Person");

//所有public方法
Method[] methods = temp.getMethods();
for (Method method : methods)
{
    System.out.println(method);
}

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

//获取所有方法(任意类型)
Method[] declaredMethods = temp.getDeclaredMethods();
for (Method declaredMethod : declaredMethods)
{
    System.out.println(declaredMethod);
}



调用方法

Class temp = Class.forName("com.model.Person");
Object o = temp.newInstance();

//执行public方法,有参数的方法需要写明参数类型
Method say = temp.getMethod("say");
say.invoke(o);

//执行declared方法,有参数的方法需要写明参数类型
Method show = temp.getDeclaredMethod("show", String.class);
//解除私有限定
show.setAccessible(true);
show.invoke(o, "aaaa");