java 反射机制

来源:互联网 发布:淘宝客服服务态度培训 编辑:程序博客网 时间:2024/06/14 12:48

JAVA反射机制

         Java反射机制是在运行状态中,对于任意一个,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

       Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

 

例子:正常情况下如果已经有一个类,则肯定可以通过类创建对象;那么如果现在要求通过一个对象找到一个类的名称,此时就需要用到反射机制。

1.      通过对象来找类。

看一个小程序:GetClassDemo01.java

package org.lxh.demo15.getclassdemo ;

class X{

};

public class GetClassDemo01{

public staticvoid main(String args[]){

           X x =new X() ;  // 实例化X类的对象

           System.out.println(x.getClass().getName());         //得到对象所在的类

}

};

javac  -d .  GetClassDemo01.java

java  org.lxh.demo15.getclassdemo.GetClassDemo01

理解class类:所有类的对象实际上都是class类的实例,所有的对象都可以转变为class类型表示。

2.      反射的源头:class,三种实例化class类的方式。

看一个程序:GetClassDemo02.java

package org.lxh.demo15.getclassdemo ;

class X{

};

public class GetClassDemo02{

public staticvoid main(String args[]){

           Class<?>c1 = null ;           // 指定泛型

           Class<?>c2 = null ;           // 指定泛型

           Class<?>c3 = null ;           // 指定泛型

           try{

                    //以下的操作形式是在开发中最常用的一种形式

                    c1= Class.forName("org.lxh.demo15.getclassdemo.X") ;

           }catch(ClassNotFoundExceptione){

                    e.printStackTrace();

           }

           c2 =new X().getClass() ;           //通过Object类中的方法实例化

           c3 =X.class ;    // 通过类.class实例化

           System.out.println("类名称:" + c1.getName())  ;      //得到类的名称

         System.out.println("类名称:" + c2.getName())  ;      //得到类的名称

           System.out.println("类名称:" + c3.getName())  ;      //得到类的名称

}

};

javac  -d  . GetClassDemo02.java

java  org.lxh.demo15.getclassdemo.GetClassDemo02

3.      取得类的结构:

getInterfaces()

getSuperclass()

getConstructors()

getMethods()

getDeclaredFields() //本类属性

getFields() //父类公共属性

看一个小程序:GetMethodDemo:

package org.lxh.demo15.classinfodemo ;

import java.lang.reflect.Method ;    // 导入构造方法的包

import java.lang.reflect.Modifier ;   // 导入构造方法的包

public class GetMethodDemo{

public staticvoid main(String args[]){

           Class<?>c1 = null ;           // 声明Class对象

           try{

                    c1= Class.forName("org.lxh.demo15.Person") ;    //实例化对象

           }catch(ClassNotFoundExceptione){

                    e.printStackTrace();

           }

           Methodm[] = c1.getMethods() ;     //取得全部方法

           for(inti=0;i<m.length;i++){

                    Class<?>r = m[i].getReturnType() ;         //得到返回值类型

                    Class<?>p[] = m[i].getParameterTypes() ;      //取得全部参数的类型

                    intxx = m[i].getModifiers() ;    //得到修饰符

                    System.out.print(Modifier.toString(xx)+ " ") ;         //输出修饰符

                    System.out.print(r+ " ") ;

                    System.out.print(m[i].getName());

                    System.out.print("(");

                    for(intj=0;j<p.length;j++){

                             System.out.print(p[j].getName()+ " " + "arg" + j) ;

                             if(j<p.length-1){

                                       System.out.print(",");

                             }

                    }

                    System.out.print(")");

                    System.out.println();

           }

}

};

Person类:

package org.lxh.demo15 ;

interface China{         //定义China接口

public staticfinal String NATIONAL = "China" ;        //定义全局常量

public staticfinal String AUTHOR = "李兴华" ;       //定义全局常量

public voidsayChina() ;             // 无参的,没有返回值的方法

public StringsayHello(String name,int age) ;  //定义有两个参数的方法,并返回内容

}

public class Person implements China{

private Stringname ;

private int age;

publicPerson(){        // 无参构造

}

publicPerson(String name){

           this.name= name ; // 设置name属性

}

publicPerson(String name,int age){

           this(name);

           this.age= age ;

}

public voidsayChina(){     // 覆写方法

           System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ;

}

public StringsayHello(String name,int age){

           returnname + ",你好!我今年:" +age + "岁了!" ;

}

public voidsetName(String name){

           this.name= name ;

}

public voidsetAge(int age){

           this.age= age ;

}

public StringgetName(){

           returnthis.name ;

}

public intgetAge(){

           returnthis.age ;

}

};

javac  -d .  GetMethodDemo.java

javac  -d .  Person.java

java  org.lxh.demo15.classinfodemo.GetMethodDemo

介绍一下随笔提示功能。

4.      通过反射调用类中的的方法、setter/getter方法、属性、数组

看一个程序:InvokeSayChinaDemo

package org.lxh.demo15.invokedemo ;

import java.lang.reflect.Method ;

public class InvokeSayChinaDemo{

public static voidmain(String args[]){

           Class<?>c1 = null ;

           try{

                    c1= Class.forName("org.lxh.demo15.Person") ;    //实例化Class对象

           }catch(Exceptione){}

           try{

                    Method  met = c1.getMethod("sayChina") ;         //找到sayChina()方法

                    met.invoke(c1.newInstance());       //调用方法。c1.newInstance()是通过无参构造实例化的对象

           }catch(Exceptione){

                    e.printStackTrace();

           }

}

};

javac  -d .  InvokeSayChinaDemo.java

javac  -d .  Person.java

java  org.lxh.demo15.invokedemo.InvokeSayChinaDemo

看一个程序:InvokeSayHelloDemo

package org.lxh.demo15.invokedemo ;

import java.lang.reflect.Method ;

public class InvokeSayHelloDemo{

public staticvoid main(String args[]){

           Class<?>c1 = null ;

           try{

                    c1= Class.forName("org.lxh.demo15.Person") ;    //实例化Class对象

           }catch(Exceptione){}

           try{

                    Method  met =c1.getMethod("sayHello",String.class,int.class) ;       //找到sayChina()方法

                    Stringrv = null ;

                    rv= (String)met.invoke(c1.newInstance(),"李兴华",30);      //调用方法

                    System.out.println(rv);

           }catch(Exceptione){

                    e.printStackTrace();

           }

}

};

javac  -d .  InvokeSayHelloDemo.java

javac  -d .  Person.java

java  org.lxh.demo15.invokedemo.InvokeSayHelloDemo

操作属性:要注意的是一般属性都是封装的,我们通过反射调用setget方法来实现对属性的操控。

看一个程序:InvokeSetGetDemo

package org.lxh.demo15.invokedemo ;

import java.lang.reflect.Method ;

public class InvokeSetGetDemo{

public staticvoid main(String args[]){

           Class<?>c1 = null ;

           Objectobj = null ;

           try{

                    c1= Class.forName("org.lxh.demo15.Person") ;    //实例化Class对象

           }catch(Exceptione){}

           try{

                    obj= c1.newInstance() ;

           }catch(Exceptione){}

         setter(obj,"name","钟汉良",String.class) ;   //调用setter方法

           setter(obj,"age",39,int.class);        //调用setter方法

           System.out.print("姓名:") ;

           getter(obj,"name");

           System.out.print("年龄:") ;

           getter(obj,"age");

}

/**

           Objectobj:要操作的对象

           Stringatt:要操作的属性

           Objectvalue:要设置的属性内容

           Class<?>type:要设置的属性类型

*/

public staticvoid setter(Object obj,String att,Object value,Class<?> type){

           try{

                    Methodmet = obj.getClass().getMethod("set"+initStr(att),type) ;       //得到setter方法

                    met.invoke(obj,value);    //设置setter的内容

           }catch(Exceptione){

                    e.printStackTrace();

           }

}

public staticvoid getter(Object obj,String att){

           try{

                    Methodmet = obj.getClass().getMethod("get"+initStr(att)) ;       //得到setter方法

                    System.out.println(met.invoke(obj));     //调用getter取得内容

           }catch(Exceptione){

                    e.printStackTrace();

           }

}

public staticString initStr(String old){      //将单词的首字母大写

           Stringstr = old.substring(0,1).toUpperCase() + old.substring(1) ;

           returnstr ;

}

};

javac  -d .  InvokeSetGetDemo.java

javac  -d .  Person.java

java  org.lxh.demo15.invokedemo.InvokeSetGetDemo

5.      为什么、什么时候会用到反射机制:

反射 可以通过配置文件进行加载类

如果通过配置文件调用所需的方法(配置文件取出的值为字符串)正向是不可以调用的 所以需要反射。

显然学过spring的朋友一定明白了,为什么可以通过配置文件就可以让我们获得指定的方法和变量,在我们创建对象的时候都是通过传进string实现的,就好像你需要什么,我们去为你生产,还有我们一直在用Object,这就说明java语言的动态特性,依赖性大大的降低了。

我们在写程序的时候并不知道需要调用某个对象的哪个方法,只有程序运行后,我们才能够知道。或许我们需要根据客户端传过来的某个String参数的值来判断我们应该执行哪个方法。在这种情况下JAVA的反射执行就可以帮上忙了。