浅析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);

}

你可能感兴趣的:(浅析java.lang.Class)