java反射机制详解

来源:互联网 发布:巴宝莉女士香水知乎 编辑:程序博客网 时间:2024/04/28 14:38

Java反射机制

一、什么是反射机制 
        简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字, 
    那么就可以通过反射机制来获得类的所有信息。 

二、哪里用到反射机制 
         有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码, 
    Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成 
    驱动对象实例,并不知道它的具体含义。听了反射机制这节课后,才知道,原来这就是反射,现在很多开 
    框架都用到反射机制,hibernate、struts都是用反射机制实现的。

三、反射机制的优点与缺点 
         为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念, 
    静态编译:在编译时确定类型,绑定对象,即通过。 
    动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多 
    态的应用,有以降低类之间的藕合性。 
        一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中 
    它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编 
    译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如 
    这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能 
    的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功 
    能。 
       它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 
    满足我们的要求。这类操作总是慢于只直接执行相同的操作。 

四、利用反射机制能获得什么信息 

   1.获得各种构造函数,动态创建不同参数的对象实例。

   2.获得各种成员方法。(共有,私有,静态等)

   3.获得各种成员变量即字段。(共有,私有,静态等)

   4.获得类的其它信息。(如方法的修饰符,public,private。类的完整包名。父类或继承的接口等)

五、代码的具体实现

  1,获取字节码class对像

         要想获得类的各种信息,要先获取字节码class类对象。获取class对象的方法有3种,代码如下:

         

class Demo{      //other codes...  }     class hello{      public static void main(String[] args) {          Class<?> demo1=null;          Class<?> demo2=null;          Class<?> demo3=null;          try{              //一般尽量采用这种形式              demo1=Class.forName("Reflect.Demo");          }catch(Exception e){              e.printStackTrace();          }          //了解,非动态创建。        demo2=new Demo().getClass();                                                                                                       //了解,非动态创建。       demo3=Demo.class; System.out.println("类名称 "+demo1.getName()); System.out.println("类名称 "+demo2.getName()); System.out.println("类名称 "+demo3.getName()); } }

 【运行结果】: 

类名称   Reflect.Demo 

类名称   Reflect.Demo 

类名称   Reflect.Demo 

  2,获取构造函数,创建实例对象。

   2.1创建实例对象,通过无参构造函数

java代码:

class Person{             public String getName() {          return name;      }      public void setName(String name) {          this.name = name;      }      public int getAge() {          return age;      }      public void setAge(int age) {          this.age = age;      }      @Override      public String toString(){          return "["+this.name+"  "+this.age+"]";      }      private String name;      private int age;  }     class hello{      public static void main(String[] args) {          Class<?> demo=null;          try{              demo=Class.forName("Reflect.Person");          }catch (Exception e) {              e.printStackTrace();          }          Person per=null;          try {              per=(Person)demo.newInstance();          } catch (InstantiationException e) {              // TODO Auto-generated catch block              e.printStackTrace();          } catch (IllegalAccessException e) {              // TODO Auto-generated catch block              e.printStackTrace();          }          per.setName("Rollen");          per.setAge(20);          System.out.println(per);      }  }  
【运行结果】: 

[Rollen  20] 

但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误: 

比如我定义了一个构造函数:

public Person(String name, int age) {          this.age=age;          this.name=name;      }  

然后继续运行上面的程序,会出现: 

    java.lang.InstantiationException

 所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数 。

   2.1 通过其它构造函数创建实例对象

java代码:

class Person{             public Person() {                 }      public Person(String name){          this.name=name;      }      public Person(int age){          this.age=age;      }      public Person(String name, int age) {          this.age=age;          this.name=name;      }      public String getName() {          return name;      }      public int getAge() {          return age;      }      @Override      public String toString(){          return "["+this.name+"  "+this.age+"]";      }      private String name;      private int age;  }     class hello{      public static void main(String[] args) {          Class<?> demo=null;          try{              demo=Class.forName("Reflect.Person");          }catch (Exception e) {              e.printStackTrace();          }          Person per1=null;          Person per2=null;          Person per3=null;          Person per4=null;          //取得全部的构造函数          Constructor<?> cons[]=demo.getConstructors();          try{              per1=(Person)cons[0].newInstance();              per2=(Person)cons[1].newInstance("Rollen");              per3=(Person)cons[2].newInstance(20);              per4=(Person)cons[3].newInstance("Rollen",20);          }catch(Exception e){              e.printStackTrace();          }          System.out.println(per1);          System.out.println(per2);          System.out.println(per3);          System.out.println(per4);      }  }  
 【运行结果】: 

[null  0] 

[Rollen  0] 

[null  20] 

[Rollen  20] 

  3  反射成员方法

java代码:

public class TestRef {     public static void main(String args[]) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {         Foo foo = new Foo("这个一个Foo对象!");         Class clazz = foo.getClass();         Method m1 = clazz.getDeclaredMethod("outInfo");         Method m2 = clazz.getDeclaredMethod("setMsg", String.class);         Method m3 = clazz.getDeclaredMethod("getMsg"); Method m4 = class.getDeclaredMethod("innerInfo");Method m5 = class.getDeclaredMethod("staticInfo");                m1.invoke(foo);                 m2.invoke(foo, "重新设置msg信息!"); m3.invoke(foo);//调用private方法关键代码m4.setAccessible(true);m4.invoke(foo);//调用静态方法m5.invoke(clazz);} class Foo {     private String msg;     public Foo(String msg) {         this.msg = msg;     }     public void setMsg(String msg) {         this.msg = msg;     }     public String getMsg() {         return msg;     }     public void outInfo() {         System.out.println("共有的方法outInfo");     } private void innerInfo(){ System.out.println("私有的方法innerInfo"); }public static staticInfo(){System.out.println("静态方法staticInfo"); }}

  4 反射成员变量

java代码如下:

class Person{             public String getName() {          return name;      }      public void setName(String name) {          this.name = name;      }      public int getAge() {          return age;      }      public void setAge(int age) {          this.age = age;      }      @Override      public String toString(){          return "["+this.name+"  "+this.age+"]";      }      private String name;      private int age;  private String sex;}  class hello {      public static void main(String[] args) throws Exception {          Class<?> demo = null;          Object obj = null;             demo = Class.forName("Reflect.Person");          obj = demo.newInstance();             Field field = demo.getDeclaredField("sex");  //操作私有属性必须执行改行代码        field.setAccessible(true);          field.set(obj, "男");      }  }

  5 反射其它信息

     5.1 获得类的完整包名。

java代码如下:

package Reflect;     /**  * 通过一个对象获得完整的包名和类名  * */  class Demo{      //other codes...  }     class hello{      public static void main(String[] args) {          Demo demo=new Demo();          System.out.println(demo.getClass().getName());      }  }  

【运行结果】:Reflect.Demo 
添加一句:所有类的对象其实都是Class的实例。 

    5.2 获得类的所有接口

java代码:

package Reflect;     interface China{      public static final String name="Rollen";      public static  int age=20;      public void sayChina();      public void sayHello(String name, int age);  }     class Person implements China{      public Person() {                 }      public Person(String sex){          this.sex=sex;      }      public String getSex() {          return sex;      }      public void setSex(String sex) {          this.sex = sex;      }      @Override      public void sayChina(){          System.out.println("hello ,china");      }      @Override      public void sayHello(String name, int age){          System.out.println(name+"  "+age);      }      private String sex;  }     class hello{      public static void main(String[] args) {          Class<?> demo=null;          try{              demo=Class.forName("Reflect.Person");          }catch (Exception e) {              e.printStackTrace();          }          //保存所有的接口          Class<?> intes[]=demo.getInterfaces();          for (int i = 0; i < intes.length; i++) {              System.out.println("实现的接口   "+intes[i].getName());          }      }  }  

【运行结果】: 

实现的接口   Reflect.China 


    5.3 获得类的所有父类。

java代码:

class hello{      public static void main(String[] args) {          Class<?> demo=null;          try{              demo=Class.forName("Reflect.Person");          }catch (Exception e) {              e.printStackTrace();          }          //取得父类          Class<?> temp=demo.getSuperclass();          System.out.println("继承的父类为:   "+temp.getName());      }  }  


【运行结果】 

继承的父类为:   java.lang.Object 

     5.4 反射父类中的方法

java代码:

class hello {      public static void main(String[] args) {          Class<?> demo = null;          Object obj=null;          try {              demo = Class.forName("Reflect.Person");          } catch (Exception e) {              e.printStackTrace();          }          try{           obj=demo.newInstance();          }catch (Exception e) {              e.printStackTrace();          }          setter(obj,"Sex","男",String.class);          getter(obj,"Sex");      }         /**      * @param obj      *            操作的对象      * @param att      *            操作的属性      * */      public static void getter(Object obj, String att) {          try {              Method method = obj.getClass().getMethod("get" + att);              System.out.println(method.invoke(obj));          } catch (Exception e) {              e.printStackTrace();          }      }         /**      * @param obj      *            操作的对象      * @param att      *            操作的属性      * @param value      *            设置的值      * @param type      *            参数的属性      * */      public static void setter(Object obj, String att, Object value,              Class<?> type) {          try {              Method method = obj.getClass().getMethod("set" + att, type);              method.invoke(obj, value);          } catch (Exception e) {              e.printStackTrace();          }      }  }
【运行结果】: 

男 
全选

     5.5 反射所有属性,权限修饰符,属性修饰符。

java代码:

class hello {      public static void main(String[] args) {          Class<?> demo = null;          try {              demo = Class.forName("Reflect.Person");          } catch (Exception e) {              e.printStackTrace();          }          System.out.println("===============本类属性========================");          // 取得本类的全部属性          Field[] field = demo.getDeclaredFields();          for (int i = 0; i < field.length; i++) {              // 权限修饰符              int mo = field[i].getModifiers();              String priv = Modifier.toString(mo);              // 属性类型              Class<?> type = field[i].getType();              System.out.println(priv + " " + type.getName() + " "                      + field[i].getName() + ";");          }          System.out.println("===============实现的接口或者父类的属性========================");          // 取得实现的接口或者父类的属性          Field[] filed1 = demo.getFields();          for (int j = 0; j < filed1.length; j++) {              // 权限修饰符              int mo = filed1[j].getModifiers();              String priv = Modifier.toString(mo);              // 属性类型              Class<?> type = filed1[j].getType();              System.out.println(priv + " " + type.getName() + " "                      + filed1[j].getName() + ";");          }      }  }

【运行结果】: 

===============本类属性======================== 

private java.lang.String sex; 

===============实现的接口或者父类的属性======================== 

public static final java.lang.String name; 

public static final int age; 


参考文章:

http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html

http://lengchaotian.iteye.com/blog/1881992

http://lavasoft.blog.51cto.com/62575/61002/

0 0
原创粉丝点击