JAVA 中的反射机制

反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧!

       一,先看一下反射的概念:

          主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

         反射是[Java](http://lib.csdn.net/base/java "Java 知识库")中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!

         看概念很晕的,继续往下看。



  二,反射机制的作用:

          1,反编译:.class-->.java

          2,通过反射机制访问java对象的属性,方法,构造方法等;

         这样好像更容易理解一些,下边我们具体看怎么实现这些功能。

  三,在这里先看一下sun为我们提供了那些反射机制中的类:

java.lang.Class;

java.lang.reflect.Constructor; java.lang.reflect.Field;

java.lang.reflect.Method;

java.lang.reflect.Modifier;

        很多反射中的方法,属性等操作我们可以从这四个类中查询。还是哪句话要学着不断的查询API,那才是我们最好的老师。

     四,具体功能实现:

            1,反射机制获取类有三种方法,我们来获取Employee类型

[java] view plain copy

print?

  1. // 第一种方式:
  2. Classc1 = Class.forName(“Employee”);
  3. // 第二种方式:
  4. //java 中每个类型都有 class 属性.
  5. Classc2 = Employee.class;
  6. // 第三种方式:
  7. //java 语言中任何一个 java 对象都有 getClass 方法
  8. Employeee = new Employee();
  9. Classc3 = e.getClass(); //c3 是运行时类 (e 的运行时类是 Employee)

    2,创建对象:获取类以后我们来创建它的对象,利用 newInstance:

[java] view plain copy

print?

  1. Class c =Class.forName(“Employee”);
  2. // 创建此 Class 对象所表示的类的一个新实例
  3. Objecto = c.newInstance(); // 调用了 Employee 的无参数构造方法.

    3, 获取属性:分为所有的属性和指定的属性:

    a,先看获取所有的属性的写法:

[java] view plain copy

print?

  1. // 获取整个类
  2. Class c = Class.forName(“java.lang.Integer”);
  3. // 获取所有的属性?
  4. Field[] fs = c.getDeclaredFields();
  5. // 定义可变长的字符串,用来存储属性
  6. StringBuffer sb = new StringBuffer();
  7. // 通过追加的方法,将每个属性拼接到此字符串中
  8. // 最外边的 public 定义
  9. sb.append(Modifier.toString(c.getModifiers()) + “ class ” + c.getSimpleName() +“{\n”);
  10. // 里边的每一个属性
  11. for(Field field:fs){
  12. sb.append(“\t”);// 空格
  13. sb.append(Modifier.toString(field.getModifiers())+“ ”);// 获得属性的修饰符,例如 public,static 等等
  14. sb.append(field.getType().getSimpleName() + “ ”);// 属性的类型的名字
  15. sb.append(field.getName()+“;\n”);// 属性的名字 + 回车
  16. }
  17. sb.append(“}”);
  18. System.out.println(sb);

    b,获取特定的属性,对比着传统的方法来学习:

[java] view plain copy

print?

  1. public static void main(String[] args) throws Exception{
  2. “white-space:pre”> // 以前的方式:
  3. /*
  4. User u = new User();
  5. u.age = 12; //set
  6. System.out.println(u.age); //get
  7. */
  8. // 获取类
  9. Class c = Class.forName(“User”);
  10. // 获取 id 属性
  11. Field idF = c.getDeclaredField(“id”);
  12. // 实例化这个类赋给 o
  13. Object o = c.newInstance();
  14. // 打破封装
  15. idF.setAccessible(true); // 使用反射机制可以打破封装性,导致了 java 对象的属性不安全。
  16. // 给 o 对象的 id 属性赋值“110”
  17. idF.set(o, “110”); //set
  18. //get
  19. System.out.println(idF.get(o));
  20. }

4,获取方法,和构造方法,不再详细描述,只来看一下关键字:

|

方法关键字

|

含义

|
|

getDeclaredMethods()

|

获取所有的方法

|
|

getReturnType()

|

获得方法的放回类型

|
|

getParameterTypes()

|

获得方法的传入参数类型

|
|

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

|

获得特定的方法

|
| | |
|

构造方法关键字

|

含义

|
|

getDeclaredConstructors()

|

获取所有的构造方法

|
|

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

|

获取特定的构造方法

|
| | |
|

父类和父接口

|

含义

|
|

getSuperclass()

|

获取某类的父类

|
|

getInterfaces()

|

获取某类实现的接口

|

     这样我们就可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。

五,反射加配置文件,使我们的程序更加灵活:

         在设计模式学习当中,学习抽象工厂的时候就用到了反射来更加方便的读取[数据库](http://lib.csdn.net/base/mysql "MySQL知识库")链接字符串等,当时不是太理解,就照着抄了。看一下.NET中的反射+配置文件的使用:

         当时用的配置文件是app.config文件,内容是XML格式的,里边填写链接数据库的内容:

[html] view plain copy

print?

  1. lt;appSettings>
  2. lt;/appSettings>
  3. configuration>

反射的写法:

[csharp] view plain copy

print?

  1. assembly.load(“当前程序集的名称”).CreateInstance(“当前命名空间名称”.要实例化的类名);
      这样的好处是很容易的方便我们变换数据库,例如我们将系统的数据库从SQL Server升级到[Oracle](http://lib.csdn.net/base/oracle "Oracle知识库"),那么我们写两份D层,在配置文件的内容改一下,或者加条件选择一下即可,带来了很大的方便。
    
     当然了,JAVA中其实也是一样,只不过这里的配置文件为.properties,称作属性文件。通过反射读取里边的内容。这样代码是固定的,但是配置文件的内容我们可以改,这样使我们的代码灵活了很多!
    

    综上为,JAVA 反射的再次学习,灵活的运用它,能够使我们的代码更加灵活,但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加,所以还要我们慎重的使用它。