Java的反射机制

Java的反射机制可以动态的加载类,实例化对象,动态的调用对象的方法等等。可以说Java的反射机制异常的强大。而且在很多的高级框架中都得到了应用。也可能说,Java的反射是高级框架功能实现的重要的一部分,所以,学好Java的反射机制对于我们高级框架的深入学习尤为重要。

Java中有的java.lang.Class对象代表Java应用程序运行时所加载的类或者接口的实例。Java中的每一个类都有一个java.lang.Class对象向对应。要获得java.lang.Class的对象有两种办法,直接通过类的.class来获得,或通过类实例例化出来的对象的getClass()方法获得。

//第一种
Class clazz=String.class;
//第二种
String str="work";
Class clazz1=str.getClass();

这样,我们就获得了String类的Class实例。有了Class实例,我们就可以对其相对应的类进行实例化对象,方法的调用,域的修改等操作。

我们还可以通过[color=red]Class.forName()[/color]方法来加载类,获得Class的实例。在写数据库的时候,我会都接触到,用它来加载数据库驱动类。forName()还有个重载的方法,除了传递一个类,还可以传递一个布尔型的值,如果为false,那么将不会初始化加载的类(一般用到它是因为类中的静态域的问题)。

我们还可以通过类的加载器,ClassLoader实例的[color=red]loadClass()[/color]方法来加载类。获得ClassLoader的方法:
[color=red]ClassLoader loader=类名.class.getClassLoader();[/color]
下面我们对类的加载器进行下简要的分析:
每个类加载器再加载类之前,会先让父类加载器先加载,如果父类加载器找不到要加载的类,再交给自己来加载。Java中有3个类加载器,[color=red]BootstrapLoader,ExtClassLoader,AppClassLoader(SystemLoader)[/color]。他们会按照[color=red]BootstrapLoader -> ExtClassLoader -> AppClassLoader[/color]这个顺序去加载类,如果找不到类,则会丢出NotClassDefFoundError异常。用ClassLoader来加载类是,不会初始化类的静态区域,只有再真正使用到这个类的时候,才初始化静态区域。前面说过,每个类有一个Class的实例对象,但是,如果同一个类,被两个加载器都加载过,就会有两个Class的实例与它对应。


[color=blue]用反射生成对象[/color],我们可以调用Class中的newInstance()方法来生成对象,例如

Class clazz=String.class;
//生成一个Object类型的对象
Object obj=clazz.newInstance();

生成的对象都是Object类型的。但是有一点要注意,用这种方法生成对象,类中必须有一个无参的构造器。另外,还有一种生成对象的办法,用java.lang.reflect.Constructor这个类来生成对象。用这种方法来生成对象可以不必有无参的构造器,我们以String类为例,用Constructor来实例化一个String类的对象,用其public String(String arg0)构造器为例子:

//获得String的Class实例
Class clazz=String.class;
//创建一个数组,这个数组用来放要实例化对象的构造器里的参数类型
Class[] param=new Class[1];
//放入构造器中的参数类型,如果有多个,按顺序放入
param[0]=String.class;
//实例化一个构造器对象,并把放着构造器参数类型的数组作为参数传进去
Constructor constructor=clazz.getConstructor(param);
//创建一个Object数组,用于放构造器中对应的值
Object[] obj=new Object[1];
//将值放入到数组中,这里要注意,param数组中放入的是什么类型,这里就要按顺序放入
obj[0]="zhang3";
//实例化对象,并把放着构造器要传入的参数的数组传到方法中
String str=(String)constructor.newInstance(obj)

这样,我们就通过java.lang.reflect.Constructor实例化出来了String类型的对象。

[color=blue]用反射调用方法[/color],通过java.lang.reflect.Method类,我们来实现对方法的调用,代码如下:

//实例化一个方法的对象,arg0是方法名,arg1是方法的参数类型,要是多个就传数组
Method method=clazz.getMethod(arg0, arg1);
//方法的调用,arg0是有次方法的对象,arg1是传入方法中的值
method.invoke(arg0, arg1);

上面的两行代码是最主要的,下面我贴出一个完整例子的代码,对照的看下,马上就明白,假设有一个Student类,它有一个setName方法,方法参数类型为String:

Class clazz=Student.class;
Object obj=clazz.newInstance();
Class[] param={String.class};
Method method=clazz.getMethod("setName", param);
Object[] value={"zhang3"};
method.invoke(obj, value);

以上便是反射对方法的调用,基本上与实例化对象大同小异。

[color=blue]用反射修改域[/color],通过java.lang.reflect.Field来实现,下面我直接贴出完整例子的代码,还是以Student类为例:

Class clazz=Student.class;
Object obj=clazz.newInstance();
//获得一个域的实例,getField()方法中的参数为域的名字
Field name=clazz.getField("name");
//*如果你的域修饰为private,那么必须调用setAccessible("true")才能对其修改
name.setAccessible("true");
//第一个参数是有此域的对象,第二个是值,这个方法是通用的,不管你的域类型是什么
name.set(obj, "zhang3");


Java的反射机制非常的强大,在这里我只是对其一些基本的功能如加载类,实例化对象,对类中方法的调用等功能进行了简单的讲解和分析。再后面,我还会对反射中的代理进行简要概述。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值