java反射机制和运用

来源:互联网 发布:淘宝恶意退款会坐牢吗 编辑:程序博客网 时间:2024/04/30 07:47

        既然这篇文章我要说的是反射,那么我们就先说一下什么是反射。

        反射

       反射是在代码运行过程中,可以动态的获取一个类的属性和方法,也可以调用任何一个类的属性和方法。这种动态的获取类的属性和动态的调用方法的机制称为反射机制,放在java中,就被称为java的反射机制。有时候我们会说一个程序有很强的动态性,其实最基本的原理就是用到了咱们的反射原理。

      例如我们在链接数据库的时候会把链接数据库的字符串写到配置文件中,这个时候我们用的就是java的反射机制,有时候我们用到的一些变量,我们也不会把这个变量写死到程序中,我们也会放到配置文件中,这也是反射,当然这个只是反射的冰山一角,今天我们就好好的说一下反射。

       Reflection

       尽管在传统的定义中,java不是一个动态语言,但是java提供了一个Reflection,这个类可以让我们动态的去加载类,属性和方法。

       反射的运用

       假设我们有这么一个要求,我需要一个Hello的类的sayHello的方法,这个方法可能被中国人执行:你好。也可能被外国人执行,那就是:"Hello",这样的话我需要写两个类来实现一个接口,一个sayHello的接口,但是我需要两个类来实现,那么好了,如果我今天用的是中国人的sayHello(),明天用外国人的几口来实现,怎么办。这个时候就是反射的用处了。 

      下边我就先写一个简短的接口lpackage Reflect;

package Reflect;/** * 一个中国的人的接口 * @author mengh * */interface Person{public static final String name="zhangsan";public static int age=20;public void sayHello(String name,int age);public void saySex(String sex);}/** * 一个中国人的类 * @author mengh * */class Chinese implements Person{private String flag;public Chinese(){}public Chinese(String flag){System.out.println(flag);this.flag = flag;}@Overridepublic void sayHello(String name, int age) {System.out.println("中国人:" + name + " " + age + "你好");}@Overridepublic void saySex(String sex) {System.out.println(sex);}}/** * 一个外国人的类 * @author mengh * */class Foreign implements Person{private String flag;public Foreign(){}public Foreign(String flag){System.out.println(flag);this.flag = flag;}@Overridepublic void sayHello(String name, int age) {System.out.println("外国人:" + name + " " + age + "Hello");}@Overridepublic void saySex(String sex) {System.out.println(sex);}}

      然后我们写个方法,来分别获取他的类型,方法名和执行方法。
public class Hello {public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{Class<?> demo = null;try {//通过完整的类型路径获取类demo = Class.forName("Reflect.Chinese");} catch (Exception e) {e.printStackTrace();}//通过newInstance()来创建对象Object obj = demo.newInstance(); //使用默认构造函数获取对象        Object objType =  demo.getConstructor(new Class[]{}).newInstance(new Object[]{});//获取objType的sayHello方法        Method helloMethod = demo.getMethod("sayHello",new Class[]{String.class,int.class});        //执行demo里边的sayHello()方法,        Object result = helloMethod.invoke(objType, new Object[]{"张三",new Integer(25)});                //创建一个带有构造函数参数的类对象        Object objType2 = demo.getConstructor(new Class[] {String.class}).newInstance(new Object[]{"这是一个带参数的构造函数"});        Method methodCon = demo.getMethod("saySex",new Class[]{String.class});        methodCon.invoke(objType2,new Object[]{"我是一个男的,而且是个帅哥"});Field[] fs = demo.getDeclaredFields();for (Field field : fs) {//Modifiers是private的, 申明的字段属性field.getType().getSimpleName(),field.getName()获取变量变量名称,filed的所属类别  System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getType().getSimpleName() + " "  + field.getName() + " " + field.getClass() );}}}
      结果如下:


        说了这么多,写了这么多,我想大家对反射也有了一个基本的认识,在代码中,我从没有写过Chinese和Forgin这两个类的引用,但是我一样可以执行里边的方法,包括构造函数。这样也就实现了他的动态语言的效果。

      如果还觉得这样写有些乱,这里有一个基本的表格,大家可以参考,用来获取对应的属性或者方法。

方法关键字

含义

getDeclaredMethods()

获取所有的方法

getReturnType()

获得方法的放回类型

getParameterTypes()

获得方法的传入参数类型

getDeclaredMethod("方法名",参数类型.class,……)

获得特定的方法

 

 

构造方法关键字

含义

getDeclaredConstructors()

获取所有的构造方法

getDeclaredConstructor(参数类型.class,……)

获取特定的构造方法

 

 

父类和父接口

含义

getSuperclass()

获取某类的父类

getInterfaces()

获取某类实现的接口

       说到这里,相信大家对反射也有一个基本的认识了,其实非常的简单,就是   Class<>里边的一些属性和方法的调用,然后我们在XML里边读取对应的属性就可以了,是不是非常的简单。下篇文章我们介绍反射和泛型的关系。   


0 0