posts - 56, comments - 54, trackbacks - 0, articles - 4
   ::  ::  :: 联系 :: 聚合  :: 管理

反射机制---Java的动态特性之一

Posted on 2006-04-14 17:02 Terry的Blog 阅读(1932) 评论(0)  编辑  收藏 所属分类: java语言

Reflection是Java的一个重要特性。这种机制可以让我们通过类名,方法名,数据成员名来得到相关的元素。
关键类java.lang.Class:这个也是Object的子类 是利用反射机制的起点。
1:产生Class object
使用getClass()
String str = "abc";
Class c1 = str.getClass();

使用Class.getSuperclass();
Button b = new Button();
Class c1 = b.getClass();
Class c2 = c1.getSuperclass();

使用static method Class.forName()
Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c3 = Class.forName ("java.util.LinkedList$Entry");

使用 类名.class
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;

使用primitive wrapper classes的TYPE
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;

2:使用 Class object

package  reflection;

import  java.lang.reflect.Constructor;
import  java.lang.reflect.Field;
import  java.lang.reflect.Method;
import  java.lang.reflect.Modifier;
import  java.util.HashMap;

public   class  TestRef  {

    
public   static   void  main(String[] args)  throws  Exception {
        TestRef testRef 
=   new  TestRef();
        Class clazz 
=  TestRef. class ;
        System.out.println(
" getPackage() =  "   +  clazz.getPackage().getName());
       
//  getModifiers()的返回值可以包含类的种类信息。比如是否为public,abstract,static
       int  mod  =  clazz.getModifiers();
        System.out.println(
" Modifier.isAbstract(mod) =  " + Modifier.isAbstract(mod));
        System.out.println(
" getName() =  " + clazz.getName());
        System.out.println(
" getSuperclass() =  " + clazz.getSuperclass().getName());
        System.out.println(
" getInterfaces() =  " + clazz.getInterfaces()); // 实现了哪些Interface
       System.out.println( " clazz.getDeclaredClasses() =  " + clazz.getDeclaredClasses()); // 包含哪些内部类
       System.out.println( " getDeclaringClass() =  " + clazz.getDeclaringClass()); // 如果clazz是inner class 那么返回其outer class
        
        System.out.println(
" ---------- " );
        Constructor[] constructor 
=  clazz.getDeclaredConstructors(); // 返回一组构造函数 Constructor[]
         if  (constructor  !=   null ) {
            
for  ( int  i  =   0 ; i  <  constructor.length; i ++ {
                System.out.println(constructor[i].getName());
            }

        }

        
        System.out.println(
" ---------- " );
        Method[] method 
=  clazz.getDeclaredMethods();  //  Method[]
         if  (method  !=   null ) {
            
for  ( int  i  =   0 ; i  <  method.length; i ++ {
                System.out.println(method[i].getName());
            }

        }

        
        System.out.println(
" ---------- " );
        Field[] field 
=  clazz.getDeclaredFields();  //  Field[]
         if  (field  !=   null ) {
            
for  ( int  i  =   0 ; i  <  field.length; i ++ {
                System.out.println(field[i].getName());
                System.out.println(field[i].getType().getName());
                System.out.println(field[i].get(testRef));
            }

        }

        
       
//  动态生成instance(无参数)
       Class clz  =  Class.forName( " reflection.TestRef " );
        Object obj 
=  clz.newInstance();
        System.out.println(((TestRef)obj).getStr());
        
       
//  动态生成instance(有参数)
       Class[] params  =   new  Class[] {String. class int . class double . class } ;
        Constructor construct 
=  clz.getConstructor(params);
       
//  JDK1.5的情况下可以直接用{"haha",999,100.01}作为参数        
       Object obj2  =  construct.newInstance( new  Object[] { " haha " new  Integer( 999 ),  new  Double( 100.01 )} ); 
        System.out.println(((TestRef)obj2).getStr());
        
       
//  动态调用method(public method)
       Class[] params2  =   new  Class[] {String. class } ;
        Method methods 
=  clz.getMethod( " setStr " , params2);
        methods.invoke(testRef, 
new  Object[] { " invoke method " } );
        System.out.println(testRef.getStr());
        
       
//  动态改变field内容(public field)
       Field fields  =  clz.getField( " str " );
        fields.set(testRef, 
" set field's value " );
        System.out.println(testRef.getStr());
        
    }


  
public  TestRef() {
        System.out.println(
" --- complete TestRef() --- " );
    }

    
   
public  TestRef(String str,  int  i,  double  d) {
        
this .str  =  str;
        
this .i  =  i;
        
this .d  =  d;
        System.out.println(
" --- complete TestRef(String str, int i, double d) --- " );
    }

    
   
public  String str  =   " I'm a string " ;

   
int  i  =   1 ;

   
double  d  =   3.14 ;

    HashMap map 
=   new  HashMap();

    
public   double  getD()  {
        
return  d;
    }


   
public   void  setD( double  d)  {
        
this .d  =  d;
    }


   
public   int  getI()  {
        
return  i;
    }


   
public   void  setI( int  i)  {
        
this .i  =  i;
    }


   
public  HashMap getMap()  {
        
return  map;
    }


   
public   void  setMap(HashMap map)  {
        
this .map  =  map;
    }


   
public  String getStr()  {
        
return  str;
    }


   
public   void  setStr(String str)  {
        
this .str  =  str;
    }

}


3说明:
上面代码的运行环境是JDK1.4.2_08
动态得到方法getMethod()和动态得到数据成员getField()时要求访问级别是public的。但是相应的getDeclaredMethods() 和getDeclaredFields()可以得到private的元素。

4补充:
public class ReflectSecurity {
    public static void main(String[] args) {
        try {
            TwoString ts = new TwoString("a", "b");
            Field field = clas.getDeclaredField("m_s1");
//          field.setAccessible(true);
            System.out.println("Retrieved value is " + field.get(inst));

        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
    }
}

如果我们编译这一程序时,不使用任何特定参数直接从命令行运行,它将在field.get(inst)调用中抛出一个Class异常。
如果我们不注释field.setAccessible (true)代码行,那么重新编译并重新运行该代码,它将运行成功。
最 后,如果我们在命令行添加了JVM参数 -Djava.security.manager 以实现安全性管理器,它仍然将不能通过运行,会抛出java.security.AccessControlException,除非我们定义了 ReflectSecurity类的许可权限。



只有注册用户登录后才能发表评论。


网站导航: