最简单的Java反射机制

本文深入探讨了Java中的反射机制,它允许程序在运行时动态地获取类的信息并调用其方法。通过实例,解释了如何使用Class.forName()、Class对象的getConstructor()和getMethod()方法创建和操作类实例。此外,还介绍了Field、Method和Constructor在反射中的作用,以及Method的invoke()方法用于调用对象方法的方式。
摘要由CSDN通过智能技术生成

Java中非常有特点的一个机制就是「反射」。反射可以理解为与正射相对立,正射就是我们知道一个类的作用,通过实例化一个实例对象,直接调用其方法。

例如定义如下一个Orange类:

public class Orange {
    private int price;
    public String name;
    public void setPrice(int price)
    {
        this.price = price;
    }
    public int getPrice()
    {
        return this.price;
    }
}

我们已经知道这个类有一个私有域price,以及两个方法。正射的过程如下:

        Orange o1 = new Orange();
        o1.setPrice(5);
        System.out.println(o1.getPrice());

正射就是直接实例化已知类的对象,通过对象调用类的方法。它在编译的时候就已经知道属于什么类,而反射在编译阶段并不会知道要初始化的类对象是什么,因此无法通过new来创造实例,而是在运行阶段,通过反射机制来了解到要操作的类是什么,并获得类的构造,以及调用类的方法。

具体如下面的代码:

        try
        {
            Class clz = Class.forName("pack2.Orange");
            Constructor orangeConstructor = clz.getConstructor();
            Orange o2 = (Orange)orangeConstructor.newInstance();
            Method setPriceMethod = clz.getMethod("setPrice", int.class);
            setPriceMethod.invoke(o2, 10);
            System.out.println(o2.getPrice());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

下面对这些代码进行详细解析。

Class类

在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时的类型标识,这个信息跟踪者每个对象所属的类,保存这些信息的类称为Class。

有如下三种方式得到Class对象:

1.使用静态方法Class.forName(),在知道类的路径时就可以使用:

Class clz = Class.forName("pack2.Orange");

2.使用.class方法,只适用于编译时就知道要操作的class:

Class clz2 = String.class;

3.使用类对象的getClass()方法:

String str1 = new String("abc");
Class clz2 = str1.getClass();

创造Class对象

有两种方式创造Class实例对象:

1.通过Class对象的newInstance()方法,这种方式只能调用无参的构造方法;

Class clz = Class.forName("pack2.Orange");
Orange o3 = (Orange)clz.newInstance();

2.通过Constructor对象的newInstance()方法,这种方式可以任意指定实例化时的构造方法:(代码中还是无参构造方法,可以自己改写下)

Class clz = Class.forName("pack2.Orange");
Constructor orangeConstructor = clz.getConstructor();
Orange o2 = (Orange)orangeConstructor.newInstance();

Field,Method与Constructor

Field,Method和Constructor都可以利用反射分析类的能力,分别描述类的域,类的方法和类的构造器。这三个类都有一个getName方法,用于返回项目的名称(编译时类型,有别于运行时类型)。

Field

Field[] fields = clz.getFields();
for(Field field: fields)
{
    System.out.println(field);
    System.out.println(field.getName());
}

输出为:

public java.lang.String pack2.Orange.name
name

可见Class对象的getFields方法只能得到非私有域,如果想要得到私有变量,需要使用getDeclaredFields

Method和Constructor也是类似的,在此不重复介绍了。

invoke函数

值得注意的是,Method类中有一个invoke成员方法,可以利用invoke方法调用一个对象所描述的方法:

setPriceMethod.invoke(o2, 10);

括号里的参数第一个为类对象,后面的参数长度是可变的,与Method对象所描述的方法的参数对应。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值