java反射机制优缺点

时间:2022-09-06 21:15:07

通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们.


理论的东东太多也没用,下面我们看看实践 Demo ~



Demo:

[java]  view plain  copy    
  1. package cn.lee.demo;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4. import java.lang.reflect.Field;  
  5. import java.lang.reflect.InvocationTargetException;  
  6. import java.lang.reflect.Method;  
  7. import java.lang.reflect.Modifier;  
  8. import java.lang.reflect.TypeVariable;  
  9.   
  10. public class Main {  
  11.     /** 
  12.      * 为了看清楚Java反射部分代码,所有异常我都最后抛出来给虚拟机处理! 
  13.      * @param args 
  14.      * @throws ClassNotFoundException 
  15.      * @throws InstantiationException 
  16.      * @throws IllegalAccessException 
  17.      * @throws InvocationTargetException  
  18.      * @throws IllegalArgumentException  
  19.      * @throws NoSuchFieldException  
  20.      * @throws SecurityException  
  21.      * @throws NoSuchMethodException  
  22.      */  
  23.     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException, NoSuchMethodException {  
  24.         // TODO Auto-generated method stub  
  25.           
  26.         //Demo1.  通过Java反射机制得到类的包名和类名  
  27.         Demo1();  
  28.         System.out.println("===============================================");  
  29.           
  30.         //Demo2.  验证所有的类都是Class类的实例对象  
  31.         Demo2();  
  32.         System.out.println("===============================================");  
  33.           
  34.         //Demo3.  通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在],无参构造  
  35.         Demo3();  
  36.         System.out.println("===============================================");  
  37.           
  38.         //Demo4:  通过Java反射机制得到一个类的构造函数,并实现构造带参实例对象  
  39.         Demo4();  
  40.         System.out.println("===============================================");  
  41.           
  42.         //Demo5:  通过Java反射机制操作成员变量, set 和 get  
  43.         Demo5();  
  44.         System.out.println("===============================================");  
  45.           
  46.         //Demo6: 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等  
  47.         Demo6();  
  48.         System.out.println("===============================================");  
  49.           
  50.         //Demo7: 通过Java反射机制调用类中方法  
  51.         Demo7();  
  52.         System.out.println("===============================================");  
  53.           
  54.         //Demo8: 通过Java反射机制获得类加载器  
  55.         Demo8();  
  56.         System.out.println("===============================================");  
  57.           
  58.     }  
  59.       
  60.     /** 
  61.      * Demo1: 通过Java反射机制得到类的包名和类名 
  62.      */  
  63.     public static void Demo1()  
  64.     {  
  65.         Person person = new Person();  
  66.         System.out.println("Demo1: 包名: " + person.getClass().getPackage().getName() + ","   
  67.                 + "完整类名: " + person.getClass().getName());  
  68.     }  
  69.       
  70.     /** 
  71.      * Demo2: 验证所有的类都是Class类的实例对象 
  72.      * @throws ClassNotFoundException  
  73.      */  
  74.     public static void Demo2() throws ClassNotFoundException  
  75.     {  
  76.         //定义两个类型都未知的Class , 设置初值为null, 看看如何给它们赋值成Person类  
  77.         Class<?> class1 = null;  
  78.         Class<?> class2 = null;  
  79.           
  80.         //写法1, 可能抛出 ClassNotFoundException [多用这个写法]  
  81.         class1 = Class.forName("cn.lee.demo.Person");  
  82.         System.out.println("Demo2:(写法1) 包名: " + class1.getPackage().getName() + ","   
  83.                 + "完整类名: " + class1.getName());  
  84.           
  85.         //写法2  
  86.         class2 = Person.class;  
  87.         System.out.println("Demo2:(写法2) 包名: " + class2.getPackage().getName() + ","   
  88.                 + "完整类名: " + class2.getName());  
  89.     }  
  90.       
  91.     /** 
  92.      * Demo3: 通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在] 
  93.      * @throws ClassNotFoundException  
  94.      * @throws IllegalAccessException  
  95.      * @throws InstantiationException  
  96.      */  
  97.     public static void Demo3() throws ClassNotFoundException, InstantiationException, IllegalAccessException  
  98.     {  
  99.         Class<?> class1 = null;  
  100.         class1 = Class.forName("cn.lee.demo.Person");  
  101.         //由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数哈~  
  102.         Person person = (Person) class1.newInstance();  
  103.         person.setAge(20);  
  104.         person.setName("LeeFeng");  
  105.         System.out.println("Demo3: " + person.getName() + " : " + person.getAge());  
  106.     }  
  107.       
  108.     /** 
  109.      * Demo4: 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象 
  110.      * @throws ClassNotFoundException  
  111.      * @throws InvocationTargetException  
  112.      * @throws IllegalAccessException  
  113.      * @throws InstantiationException  
  114.      * @throws IllegalArgumentException  
  115.      */  
  116.     public static void Demo4() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException  
  117.     {  
  118.         Class<?> class1 = null;  
  119.         Person person1 = null;  
  120.         Person person2 = null;  
  121.           
  122.         class1 = Class.forName("cn.lee.demo.Person");  
  123.         //得到一系列构造函数集合  
  124.         Constructor<?>[] constructors = class1.getConstructors();  
  125.           
  126.         person1 = (Person) constructors[0].newInstance();  
  127.         person1.setAge(30);  
  128.         person1.setName("leeFeng");  
  129.           
  130.         person2 = (Person) constructors[1].newInstance(20,"leeFeng");  
  131.           
  132.         System.out.println("Demo4: " + person1.getName() + " : " + person1.getAge()  
  133.                 + "  ,   " + person2.getName() + " : " + person2.getAge()  
  134.                 );  
  135.           
  136.     }  
  137.       
  138.     /** 
  139.      * Demo5: 通过Java反射机制操作成员变量, set 和 get 
  140.      *  
  141.      * @throws IllegalAccessException  
  142.      * @throws IllegalArgumentException  
  143.      * @throws NoSuchFieldException  
  144.      * @throws SecurityException  
  145.      * @throws InstantiationException  
  146.      * @throws ClassNotFoundException  
  147.      */  
  148.     public static void Demo5() throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException, InstantiationException, ClassNotFoundException  
  149.     {  
  150.         Class<?> class1 = null;  
  151.         class1 = Class.forName("cn.lee.demo.Person");  
  152.         Object obj = class1.newInstance();  
  153.           
  154.         Field personNameField = class1.getDeclaredField("name");  
  155.         personNameField.setAccessible(true);  
  156.         personNameField.set(obj, "胖虎先森");  
  157.           
  158.           
  159.         System.out.println("Demo5: 修改属性之后得到属性变量的值:" + personNameField.get(obj));  
  160.           
  161.     }  
  162.       
  163.   
  164.     /** 
  165.      * Demo6: 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等 
  166.      * @throws ClassNotFoundException  
  167.      */  
  168.     public static void Demo6() throws ClassNotFoundException  
  169.     {  
  170.         Class<?> class1 = null;  
  171.         class1 = Class.forName("cn.lee.demo.SuperMan");  
  172.           
  173.         //取得父类名称  
  174.         Class<?>  superClass = class1.getSuperclass();  
  175.         System.out.println("Demo6:  SuperMan类的父类名: " + superClass.getName());  
  176.           
  177.         System.out.println("===============================================");  
  178.           
  179.           
  180.         Field[] fields = class1.getDeclaredFields();  
  181.         for (int i = 0; i < fields.length; i++) {  
  182.             System.out.println("类中的成员: " + fields[i]);  
  183.         }  
  184.         System.out.println("===============================================");  
  185.           
  186.           
  187.         //取得类方法  
  188.         Method[] methods = class1.getDeclaredMethods();  
  189.         for (int i = 0; i < methods.length; i++) {  
  190.             System.out.println("Demo6,取得SuperMan类的方法:");  
  191.             System.out.println("函数名:" + methods[i].getName());  
  192.             System.out.println("函数返回类型:" + methods[i].getReturnType());  
  193.             System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));  
  194.             System.out.println("函数代码写法: " + methods[i]);  
  195.         }  
  196.           
  197.         System.out.println("===============================================");  
  198.           
  199.         //取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到哈  
  200.         Class<?> interfaces[] = class1.getInterfaces();  
  201.         for (int i = 0; i < interfaces.length; i++) {  
  202.             System.out.println("实现的接口类名: " + interfaces[i].getName() );  
  203.         }  
  204.           
  205.     }  
  206.       
  207.     /** 
  208.      * Demo7: 通过Java反射机制调用类方法 
  209.      * @throws ClassNotFoundException  
  210.      * @throws NoSuchMethodException  
  211.      * @throws SecurityException  
  212.      * @throws InvocationTargetException  
  213.      * @throws IllegalAccessException  
  214.      * @throws IllegalArgumentException  
  215.      * @throws InstantiationException  
  216.      */  
  217.     public static void Demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException  
  218.     {  
  219.         Class<?> class1 = null;  
  220.         class1 = Class.forName("cn.lee.demo.SuperMan");  
  221.           
  222.         System.out.println("Demo7: \n调用无参方法fly():");  
  223.         Method method = class1.getMethod("fly");  
  224.         method.invoke(class1.newInstance());  
  225.           
  226.         System.out.println("调用有参方法walk(int m):");  
  227.         method = class1.getMethod("walk",int.class);  
  228.         method.invoke(class1.newInstance(),100);  
  229.     }  
  230.       
  231.     /** 
  232.      * Demo8: 通过Java反射机制得到类加载器信息 
  233.      *  
  234.      * 在java中有三种类类加载器。[这段资料网上截取] 
  235.  
  236.         1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 
  237.  
  238.         2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类 
  239.  
  240.         3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 
  241.      *  
  242.      * @throws ClassNotFoundException  
  243.      */  
  244.     public static void Demo8() throws ClassNotFoundException  
  245.     {  
  246.         Class<?> class1 = null;  
  247.         class1 = Class.forName("cn.lee.demo.SuperMan");  
  248.         String nameString = class1.getClassLoader().getClass().getName();  
  249.           
  250.         System.out.println("Demo8: 类加载器类名: " + nameString);  
  251.     }  
  252.       
  253.       
  254.       
  255. }  
  256. /** 
  257.  *  
  258.  * @author xiaoyaomeng 
  259.  * 
  260.  */  
  261. class  Person{  
  262.     private int age;  
  263.     private String name;  
  264.     public Person(){  
  265.           
  266.     }  
  267.     public Person(int age, String name){  
  268.         this.age = age;  
  269.         this.name = name;  
  270.     }  
  271.   
  272.     public int getAge() {  
  273.         return age;  
  274.     }  
  275.     public void setAge(int age) {  
  276.         this.age = age;  
  277.     }  
  278.     public String getName() {  
  279.         return name;  
  280.     }  
  281.     public void setName(String name) {  
  282.         this.name = name;  
  283.     }  
  284. }  
  285.   
  286. class SuperMan extends Person implements ActionInterface  
  287. {  
  288.     private boolean BlueBriefs;  
  289.       
  290.     public void fly()  
  291.     {  
  292.         System.out.println("超人会飞耶~~");  
  293.     }  
  294.       
  295.     public boolean isBlueBriefs() {  
  296.         return BlueBriefs;  
  297.     }  
  298.     public void setBlueBriefs(boolean blueBriefs) {  
  299.         BlueBriefs = blueBriefs;  
  300.     }  
  301.   
  302.     @Override  
  303.     public void walk(int m) {  
  304.         // TODO Auto-generated method stub  
  305.         System.out.println("超人会走耶~~走了" + m + "米就走不动了!");  
  306.     }  
  307. }  
  308. interface ActionInterface{  
  309.     public void walk(int m);  
  310. }  




个人觉得使用反射机制的一些地方:


1.工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory了
2.数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动
3.分析类文件:毕竟能得到类中的方法等等
4.访问一些不能访问的变量或属性:破解别人代码



Demo下载地址:http://download.csdn.net/detail/u011133213/6420969








反射的用途 Uses of Reflection

Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.

反射被广泛地用于那些需要在运行时检测或修改程序行为的程序中。这是一个相对高级的特性,只有那些语言基础非常扎实的开发者才应该使用它。如果能把这句警示时刻放在心里,那么反射机制就会成为一项强大的技术,可以让应用程序做一些几乎不可能做到的事情。


反射的缺点 Drawbacks of Reflection

Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.

尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心:

性能第一  Performance Overhead
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程序中使用反射。
安全限制  Security Restrictions
Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。。
内部暴露  Exposure of Internals
Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing  private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。