java.lang.class_浅析java.lang.Class

最近温习了一下java的反射机制,发现之前学习反射的时候没有留下只言片语,补上补上!!!

反射的概念:

比如我们想看看我们自己长什么样子,我们自己肯定看不到自己长什么样子,所以,我们借助镜子,通过镜子的反射看到我们的样子,可以看清我们自己的五官;

同理,在Java中运行的类,也有这么一面镜子,可以反射该类的一些行为和属性,而这个反射就体现在java.lang.Class中;

通过Class对象,可以得到某个类的一些行为和属性,甚至我们通过反射可以操作这个对象的行为和属性;这就是反射机制;

要想理解反射,我们先来了解一下java.lang.Class这个‘万能’的类;

获取Class实例的几种方式:

(1)通过全类名获取Class实例,这也是最常用的一种方式

public void testClassForName(){

String className = "com.test.bean.Preson";

Class clazz = Class.forName(className);

}

为什么说这是一种最常用的一种方式,相信大家都用过Spring或者MyBatis等等这类框架,在使用这类框架的时候,免不了与该框架的XML配置文件打交道,在很多配置的地方都会填写一个全类名;

看过源码的同学应该就知道,因为这些框架会先解析XML配置文件的到这个全类名,通过这个全类名来得到Class对象,完成后面的反射调用的动作;

(2)通过getClass的方式得到Class实例

public void testGetClass(Object obj){

Class clazz = obj.getClass();

}

这里为什么用Object作为入参呢?因为更多时候我们不知道外面传进来的是什么对象,使用Object接受就可以接受任何java对象,那么通过反射就可以获得到相应的Class

(3)通过类.class的形式获取

public void testClass(){

Class clazz = Person.class;

}

(4)通过类加载器的形式获取

public void testClassLoader(){

ClassLoader classLoader = this.getClass().getClassLoader();

Class clazz = classLoader.loadClass(className);

}

也就是说,我们得到Class对象,就可以为所欲为了,可以利用反射机制来调用该类的方法或者属性;

说完Class,我们说下几个常用的相关类;这几个类的使用方式都差不多;

java.lang.reflect.Constructor

这个类是专门描述某个类的构造方法,可以通过Class对象获得到类中定义的构造方法;

//获取构造器

public void testConstructor() throws Exception{

String className = "com.test.bean.Person";

Class clazz = Class.forName(className);

//通过Class对象获取Constructor对象

Constructor constructor = clazz.getConstructor();

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

}

parameterTypes:表示构造器的参数列表,如果想获取无参构造器,这个参数不要传了;

但是这个clazz.getConstructor();只能获取到构造器为public类型的,不能获取到private修饰的构造器;

//获取私有构造器

public void testConstructor() throws Exception{

String className = "com.test.bean.Person";

Class clazz = Class.forName(className);

//通过Class对象获取private 修饰的Constructor对象

Constructor constructor = clazz.getDeclaredConstructor();

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

}

同时,如果想调用私有的构造器,调用前要调用一下setAccessible(true),获取调用私有方法的权限,否则会报异常

//获取私有构造器,并执行私有构造器

public void testConstructor() throws Exception{

String className = "com.test.bean.Person";

Class clazz = Class.forName(className);

//通过Class对象获取private 修饰的Constructor对象

Constructor constructor = clazz.getDeclaredConstructor();

constructor.setAccessible(true);

//调用构造器创建实例

Object obj = constructor.newInstance();

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

}

通过上面,就会发现,Java的三大特性:封装、继承、多态,这里面的封装对反射来说是无用了,通过反射可以破坏他的封装;啊哈哈哈。。。

java.lang.reflect.Method

这个类描述了类中的方法,通过这个Method对象,可以操作类中定义的方法;

//通过反射获得类定义的Mehtod,但是获取不到private修饰的方法

Mehtod method = clazz.getMethod('setName', String.class);

//获取本类中定义的方法,包括私有方法也可以获取

Method method = clazz.getDeclaredMethod("test",String.class);

获取指定的Method的时候需要传入两个参数:

1.方法名

2.方法的参数列表类型,比如方法的入参是String类型的,那么这里就是String.class

//获取本类和父类中public的所有方法集合,但是获取不到私有方法

Method[] methods = clazz.getMethods();

//获取本类所有方法集合,包括私有方法

Method[] methods = clazz.getDeclaredMethods();

同样,在调用private修饰的方法之前,要调用setAccessible(true);

//通过method调用方法,这个才是重点

public Object invoke(Object obj,Object... args);

obj:调用哪个对象中的方法

args:方法的参数

method.invoke(clazz.newInstance(), "helloWorld");

java.lang.reflect.Field:属性

public void testField() throws Exception{

String className = "com.test.classloader.bean.Person";

Class clazz = Class.forName(className);

//先通过反射获得到实例

Object obj = clazz.newInstance();

//获取对象中指定的属性

Field field = clazz.getField("name");

//为属性赋值

field.set(obj, "hello");

System.out.println(obj);

//获取private 修饰的成员属性

Field field1 = clazz.getDeclaredField("name");

field1.setAccessible(true);

field1.set(obj, "world");

System.out.println(obj);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值