1.什么是Java的反射? 
要让Java程序能够运行,就得让Java类被Java虚拟机加载。Java类如果不被Java虚拟机加载就不能正常运行。正常情况下,我们运行的所有的程序在编译期时候就已经把那个类被加载了。Java的反射机制是在编译时并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用的是在编译期并不知道的类。这样的编译特点就是java反射。 
2.Java反射的作用? 
假如有两个程序员,一个程序员在写程序的时需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码是不能通过编译的。此时,利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。
3.Class类 
要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。
4.反射API 
反射API用于反应在当前Java虚拟机中的类、接口或者对象信息
功能 
获取一个对象的类信息. 
获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息. 
检获属于一个接口的常量和方法声明. 
创建一个直到程序运行期间才知道名字的类的实例. 
获取并设置一个对象的成员,这个成员的名字是在程序运行期间才知道. 
 
检测一个在运行期间才知道名字的对象的方法
那么如何利用反射API在运行的时候知道一个类的信息呢? 
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package  com.reflection.classForName;  import  java.lang.reflect.Field;  import  java.lang.reflect.Method;  import  javax.swing.JOptionPane;           public  class  ClassForName  {            public  ClassForName () {         String classInfo=JOptionPane.showInputDialog(null ,"输入类全路径" );       try  {            Class<?> cla=Class.forName(classInfo);          Method[] method=cla.getDeclaredMethods();          System.out.println("forName:" +cla);            for (Method me:method){             System.out.println("方法有:" +me.toString());          }            System.out.println("*****************************************************" );            Field[] field=cla.getDeclaredFields();          for (Field me:field){              System.out.println("属性有:" +me.toString());          }         } catch  (ClassNotFoundException e) {            e.printStackTrace();         }      }         public  static  void  main (String[] args)  {         new  ClassForName ();      }   } 
运行的时候,我们输入java.lang.String,那么运行结果如下:编译器联想原理:
通过上面代码,我们可以知道编译工具为什么能够一按点就能列出用户当前对象的属性和方法了。它是先获得用户输入对象的字符串,然后利用反射原理来对这样的类进行自审,从而列出该类的方法和属性。 
总结: 使用反射机制的步骤 
首先: 导入java.lang.relfect 包
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package  com.reflection.classForName;  public  class  GetClassTest  {     public  static  void  main (String[] args)  throws  InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException{         System.out.println("测试开始" );         GetClassTestObj  gctObj  =  new  GetClassTestObj ();         Class<? extends  GetClassTestObj > clazzClass = gctObj.getClass();           System.out.println("clazzClass:" +clazzClass);         GetClassTestObj  gctObj2  =  (GetClassTestObj)clazzClass.newInstance();        System.out.println("gctObj==gctOb2 :" +(gctObj == gctObj2));         System.out.println("gctObj.getClass() == gctOb2.getClass() :" +(gctObj.getClass() == gctObj2.getClass()));         gctObj2.print();         }   }            package  com.reflection.classForName;  public  class  GetClassTestObj  {     static {            System.out.println("nihao" );      }      private  String  name  =  "chen" ;      public  String  address  =  "chengdu" ;      public  void  print () {         System.out.println("name:" +name+" ,address:" +address);      }   } 
这样获得Class类对象的方法,其实是利用反射API把指定字符串的类加载到内存中,所以也叫类加载器加载方法。这样的话,它会把该类的静态方法和静态属性,以及静态代码全部加载到内存中。但这时候,对象还没有产生。所以为什么静态方法不能访问非静态属性和方法。因为静态方法和属性产生的时机在非静态属性和方法之前。 
代码示例:
反射机制不但可以例出该类对象所拥有的方法和属性,还可以获得该类的构造方法及通过构造方法获得实例。也可以动态的调用这个实例的成员方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package  com.reflection.constructor;  import  java.lang.reflect.Constructor;        public  class  ConstructorTest  {     public  static  void  main (String[] args)  {         try  {                         Class  clazz  =  Class.forName("com.reflection.constructor.Tests" );           Class[] cl=new  Class []{int .class,int .class};             Constructor con=clazz.getConstructor(cl);                                    Object  object  =  con.newInstance(33 ,66 );         } catch  (Exception e) {            e.printStackTrace();         }      }   }             class  Tests {     public  Tests (int  x,int  y) {         System.out.println(x+" ," +y);      }   } 
运行的结果是” 33 67”。说明我们已经生成了Tests这个类的一个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package  com.reflection.MethodInvoke;     import  java.lang.reflect.Method;             public  class  MethodInvoke  {         public  static  void  main (String[] args)  {            try  {               Class cla=Class.forName("javax.swing.JFrame" );              Object obj=cla.newInstance();                            Class[] classes = new  Class []{int .class, int .class};               Method  methodSize  =  cla.getMethod("setSize" , classes);                               methodSize.invoke(obj, new  Object []{new  Integer (600 ),new  Integer (300 )});                         Method methodVisible=cla.getMethod("setVisible" , new  Class []{boolean .class});                               methodVisible.invoke(obj, new  Object []{new  Boolean (true )});            } catch  (Exception e) {               e.printStackTrace();            }         }      } 
反射技术大量用于Java设计模式和框架技术,最常见的设计模式就是工厂模式(Factory)和单例模式(Singleton)。 
单例模式(Singleton) 
保证在Java应用程序中,一个类Class只有一个实例存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package  reflect;  public  class  Singleton  {              private  Singleton ()  {       }                  private  static  Singleton  instance  =  new  Singleton ();               public  static  Singleton getInstance ()  {              return  instance;       }            class  SingRun {      public  static  void  main (String[] args) {                                  Singleton x=Singleton.getInstance();                  Singleton y=Singleton.getInstance();                  System.out.println(x==y);       }   } 
第二种形式:
1 2 3 4 5 6 7 8 9 10 11 12 public  class  Singleton  {           private  static  Singleton  instance  =  null ;            public  static  synchronized  Singleton getInstance ()  {               if  (instance == null ){              instance = new  Singleton ();          }          return  instance;       }   } 
两种形式大体上是差不多的
工厂模式(Factory) 
工厂模式:著名的Jive论坛 ,就大量使用了工厂模式。为什么工厂模式是如此常用?因为工厂模式利用Java反射机制和Java多态的特性可以让我们的程序更加具有灵活性。用工厂模式进行大型项目的开发,可以很好的进行项目并行开发。就是一个程序员和另一个程序员可以同时去书写代码,而不是一个程序员等到另一个程序员写完以后再去书写代码。其中的粘合剂就是接口和配置文件。 
利用接口可以将调用和实现相分离。两个程序员可以互不影响的实现相应的功能,最后通过配置文件进行整合。 
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13    package  com.reflection.Factory;     public  interface  InterfaceTest  {        public  void  getName () ; } 
实现这个接口,重写其中定义的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27    package  com.reflection.Factory;  public  class  Test1  implements  InterfaceTest  {     @Override       public  void  getName ()  {         System.out.println("test1" );      }   }               package  com.reflection.Factory;  public  class  Test2  implements  InterfaceTest  {     @Override       public  void  getName ()  {        System.out.println("test2" );      }   } 
可以发现,当接口定义好了以后,不但可以规范代码,而且可以让程序员有条不紊的进行功能的实现。实现接口的程序员根本不用去管,这个类要被谁去调用。
工厂类,生产接口对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51       package  com.reflection.Factory;  import  java.io.InputStream;  import  java.util.Properties;  public  class  Factory {    private  static  Properties prop=new  Properties ();     static {        try  {           InputStream  ips  =  Factory.class.getClassLoader().getResourceAsStream("file.properties" );           prop.load(ips);        } catch  (Exception e) {           e.printStackTrace();        }     }              private  static  Factory factory=new  Factory ();        private  Factory () {}         public  static  Factory getFactory () {        return  factory;     }                 public   InterfaceTest getInterface () {        InterfaceTest  interfaceTest  =  null ;        try  {           String  classInfo  =  prop.getProperty("test" );            Class<?> c = Class.forName(classInfo);           Object  obj  =  c.newInstance();           interfaceTest = (InterfaceTest)obj;        } catch  (Exception e) {           e.printStackTrace();        }        return  interfaceTest;    }   } 
配置文件内容: 
通过这个类,可以发现,在调用的时候,得到的是个接口对象。而一个接口变量可以指向实现了这个接口的类对象。在利用反射的时候,我们并没有直接把类的全路径写出来,而是通过键获得值。这样的话,就有很大的灵活性,只要改变配置文件里的内容,就可以改变我们调用的接口实现类,而代码不需做任何改变。在调用的时候,我们也是通过接口调用,甚至我们可以连这个接口实现类的名字都不知道。 
调用方:
1 2 3 4 5 6 7 8 9 10 11 12 13 14       package  com.reflection.Factory;  public  class  FactoryTest  {     public  static  void  main (String[] args)  {         Factory  factory  =  Factory.getFactory();        InterfaceTest  interObj  =  factory.getInterface();         interObj.getName();       }   } 
上面的代码就是调用方法。大家可以发现,在调用的时候,我们根本没有管这个接口定义的方法要怎么样去实现它,我们只知道这个接口定义这个方法起什么作用就行了。上面代码运行结果要根据配置文件来定。如果配置文件里的内容是test=
com.reflection.Factory.Test2。那么表示调用com.reflection.Factory.Tes2这个类里实现接口的方法,这时候打印“test2”。如果配置文件里的内容是test=
com.reflection.Factory.Test1。那么表示调用com.reflection.Factory.Test1这个类里实现接口的方法,这时候打印“test1”。 
反射机制是框架技术的原理和核心部分。通过反射机制我们可以动态的通过改变配置文件(以后是XML文件)的方式来加载类、调用类方法,以及使用类属性。这样的话,对于编码和维护带来相当大的便利。在程序进行改动的时候,也只会改动相应的功能就行了,调用的方法是不用改的。更不会一改就改全身。