反射动态创建执行对象

Java的反射机制是非常强大的,反射出现之前Java只是一门静态语言,当JDK5诞生发布了注解、反射的功能之后Java的功能越发变得强大,成为了一门准动态语言弥补了Java强类型语言的不足。

通过Java的反射机制可以动态的获取到非常多的信息(如图)
在这里插入图片描述

1. 动态创建对象

package reflection.third;

public class User {
    private String name ;
    private int age;
    private static int value = 100;
    public User(){      //无参构造

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

    public String getName() {
        return name;
    }

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

    private static void print(){			//public的方法就不需要反射获取了
        System.out.println("value = " + value);
    }

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


  1. 通过newInstance方法实例化对象,只会调用类的无参构造方法进行实例化对象。如果类中没有无参构造方法强行进行构造会爆出异常
@Test
public void test1() throws Exception {
    User s1 = (User)Class.forName("reflection.third.User").newInstance();           //只会调用无参构造器进行实例化
    System.out.println(s1);
}

在这里插入图片描述

  1. 通过反射加载类的构造方法然后进行构造。
@Test
public void test2() throws Exception {
     //1. 空构造
     Constructor c1 = Class.forName("reflection.third.User").getDeclaredConstructor();
     User s1 = (User)c1.newInstance();
     System.out.println(s1);

     //2. 通过参数类型、顺序指定获取构造方法。
     Constructor c2 = Class.forName("reflection.third.User").getDeclaredConstructor(String.class,int.class);
     User s2 = (User)c2.newInstance("姓名", 1);         //注意参数类型顺序匹配
     System.out.println(s2.toString());
 }

在这里插入图片描述

建议使用Constructor构造。构造方法和Field字段、Method方法一样有四种类型。


2. 操作普通方法和静态方法

使用invoke(Object o,Object …args)执行方法,由于普通方法是实力化对象分配的方法,所以执行时需要指定是哪个实例化对象操作;而静态方法则不需要,因为静态方法不属于任何一个实例化对象。
如果修饰符是private可以调用setAccessible(true)临时的将权限提升到public进行访问。

@Test
public void test3() throws Exception{
    //1. 获取普通方法
    User user = (User)Class.forName("reflection.third.User").newInstance();
    Method setName = Class.forName("reflection.third.User").getDeclaredMethod("setName", String.class);
    setName.invoke(user,"你好");
    System.out.println(user.toString());

    //2. 获取静态方法
    Method print = Class.forName("reflection.third.User").getDeclaredMethod("print");
    print.setAccessible(true);
    print.invoke(null);			//传入空对象即可
}

在这里插入图片描述

3. 操作普通变量和静态变量

获取到的字段可以调用set(Object obj,Object …args)设置属性的值,调用get(Object obj)方法获取属性的值

@Test
public void test4() throws Exception{
    //1. 获取普通变量
    User user = (User)Class.forName("reflection.third.User").newInstance();
    Field name1 = Class.forName("reflection.third.User").getDeclaredField("name");
    name1.setAccessible(true);
    name1.set(user,"姓名");
    System.out.println(name1.get(user));

    //2. 获取静态变量
    Field name2 = Class.forName("reflection.third.User").getDeclaredField("value");
    name2.setAccessible(true);
    name2.set(null,9999);
    System.out.println(name2.get(null));
}

在这里插入图片描述

4. 总结

  1. newInstance方法实例化对象只会调用无参构造函数,如果没有无参构造函数将会报出异常。

  2. 使用反射获取一些信息时如果权限不够,可以使用setAccessible(true)来临时提升权限

  3. 反射调用静态方法时,invoke方法可以不传入实例化对象传入null即可。

  4. 反射调用静态变量时,set()、get()方法一样不需要传入实例化对象,直接传入null;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值