【Java】reflective-反射机制


前言

反射库(reflection library) 提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵Java代码的程序。这项功能被大量的运用于JavaBeans中,它是Java组件的体系结构。


一、反射是什么?

在《Java核心技术 卷1》中介绍到反射的定义;

能够分析类能力的程序称为反射(reflective)。

什么是能够分析类能力呢?
可以理解为程序运行时可以访问、检测和修改他本身状态和行为的能力。包类的属性、方法和构造器等。

二、Class类

在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个标识跟踪着每个对象的所属信息。虚拟机利用运行时类型信息选择相应的执行方法。
然而可以通过Java类访问这些信息。保存这些信息的类被称为Class
Object类中的getClass()方法会返回一个Class类的实例。

接下来介绍三种获取class对象的方法:
由于Object类是所有类的父类,所以可以得到获取Class类的第一种方法:

        //通过对象.getClass方法获取。
        User user = new User();
        Class<? extends User> aClass = user.getClass();

还可以通过调用静态方法的方法forName(className)获得类名对应的Class对象。

        //通过静态方法获取Class
        Class<?> aClass1 = Class.forName("java.lang.Math");//参数:类路径
        System.out.println("name:"+ aClass1.getName());

		//控制台打印:name:java.lang.Math

forName(classNmae)方法调用时,只有className是类名或者是接口名时才可以使用,否则会抛出一个检查时异常。所以无论何时使用这个方法都应该提供一个异常处理器。

最后可以通过.class的方式获取Class对象。

        Class<User> userClass = User.class;

上面的示例代码中可以发现,Class类其实是一个泛型类。

getNmae应用于数组类型的时候,会返回一个奇怪的名字

        System.out.println("Integer[].class.getName()===="+ Integer[].class.getName());
        System.out.println("Double[].class.getName()====" + Double[].class.getName());
        System.out.println("int[].class.getName()====" + int[].class.getName());
        //Integer[].class.getName()====[Ljava.lang.Integer;
		//Double[].class.getName()====[Ljava.lang.Double;
		//int[].class.getName()====[I

Class还有一个很实用的方法:newInstance(),可以用来动态的创建一个类的实例。newInstance()方法调用默认的构造器初始化新创建对象,如果类中没有这个对象,则会抛出异常。
如果想要调用有参数的构造器,就需要Constructor类中的newInstance(Object[] args);后续会进行讲解

        Object o = aClass.newInstance();
        System.out.println(o.toString());

三、利用反射分析类的能力

下面简要介绍一下反射机制的最重要的内容——检查类的结构。

  • 在java.lang.reflect包中提供了三个类:Field、Method和Constructor分别用于描述属性,方法和构造器。
  • Class类中的getFields()、getMethods()、getConstructors()方法用于返回类提供的public 属性方法和构造器数组,其中包括超类的公共成员。
  • Class类中getDeclaredFields()、getDeclaredMethods()、
    getDeclaredConstructors()方法用于返回类提供的全部属性方法和构造器数组,包括私有的和受保护的成员,但不包括超类的成员。
    示例代码
    创建一个User对象,包含公共和私有的属性和构造器,并继承Person对象
    创建一个Person对象,包含公共和私有的属性和构造器;
public class User  extends Person{
    public String name;
    private int age;

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

    public User() {
    }

    protected User(int age) {
        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 "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Person {
    public  String nation;
    private String desc;
    public Person(String nation) {
        this.nation = nation;
    }

    private Person(String nation, String desc) {
        this.nation = nation;
        this.desc = desc;
    }

    public Person() {
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

获取Class对象,并通过class获取对象的属性,方法和构造器。

public class Reflective {
    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("reflect.User");//参数:类路径
        Field[] fields = clazz.getFields();
        System.out.println("getFields 方法获取的属性:");
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        System.out.println("getDeclaredFields 方法获取的属性:");
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }
        Method[] methods = clazz.getMethods();
        System.out.println("getMethods 方法获取的方法:");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        Method[] declaredMethods = clazz.getDeclaredMethods();
        System.out.println("getDeclaredMethods 方法获取的方法:");
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());
        }

        Constructor<?>[] constructors = clazz.getConstructors();
        System.out.println("getConstructors 方法获取的构造器:");
        for (Constructor<?> constructor : constructors) {
            System.out.println("构造器参数个数:"+constructor.getParameterCount());
        }

        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        System.out.println("getDeclaredConstructors 方法获取的构造器:");
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("构造器参数个数:"+ declaredConstructor.getParameterCount());
        }


    }

}

四、通过反射创建实例对象

通过反射可以获取动态实例化对象:


        Class<?> clazz = Class.forName("reflect.User");//参数:类路径
        Object o = clazz.newInstance();
        System.out.println(o.toString());

        Object zhansan = clazz.getConstructor(String.class).newInstance("zhansan");
        System.out.println(zhansan);

后续还会补充反射的更多用法~~并完善文章

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值