Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods


基本学习:


     Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,

     Constructor[] getConstructors() -- 获得类的所有公共构造函数

     Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)

     Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关) 

     获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:

     Field getField(String name) -- 获得命名的公共字段

     Field[] getFields() -- 获得类的所有公共字段

     Field getDeclaredField(String name) -- 获得类声明的命名的字段

     Field[] getDeclaredFields() -- 获得类声明的所有字段 

     用于获得方法信息函数:

     Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

     Method[] getMethods() -- 获得类的所有公共方法

     Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法

     Method[] getDeclaredMethods() -- 获得类声明的所有方法 





import java.awt.Button;
import java.lang.reflect.Method;
import java.util.Hashtable;

/** *//**
 * 测试Java的反射机制
 * 
@author Amigo Xie(xiexingxing1121@126.com)
 * 
@since 2007/04/20 21:40
 
*/

public class ReflectionTest {

    
/** *//**
     * 
@param args
     
*/

    
public static void main(String[] args) throws Exception {
        ReflectionTest reflection 
= new ReflectionTest();
        reflection.getNameTest();
        System.out.println(
"");
        reflection.getMethodTest();
    }

    
    
/** *//**
     * Class的getName()方法测试
     * 
@throws Exception
     
*/

    
public void getNameTest() throws Exception {
        System.out.println(
"===========begin getNameTest============");
        String name 
= "amigo";
        Class cls 
= name.getClass();
        System.out.println(
"string class name: " + cls.getName());
        
        Button btn 
= new Button();
        Class btnClass 
= btn.getClass();
        System.out.println(
"button class name: " + btnClass.getName());
        Class superBtnClass 
= btnClass.getSuperclass();
        System.out.println(
"super button class name: " + superBtnClass.getName());
        
        Class clsTest 
= Class.forName("java.awt.Button");
        System.out.println(
"clsTest name: " + clsTest.getName());
        System.out.println(
"===========end getNameTest============");
    }

    
    
/** *//**
     * Class的getMethod()方法测试
     * 
@throws Exception
     
*/

    
public void getMethodTest() throws Exception {
        System.out.println(
"===========begin getMethodTest==========");
        Class cls 
= Class.forName("ReflectionTest");
        Class ptypes[] 
= new Class[2];
        ptypes[
0= Class.forName("java.lang.String");
        ptypes[
1= Class.forName("java.util.Hashtable");
        Method method 
= cls.getMethod("testMethod", ptypes);
        Object args[] 
= new Object[2];
        args[
0= "hello, my dear!";
        
        Hashtable ht 
= new Hashtable();
        ht.put(
"name""amigo");
        args[
1= ht;
        
        String returnStr 
= (String) method.invoke(new ReflectionTest(), args);
        System.out.println(
"returnStr= " + returnStr);
        System.out.println(
"===========end getMethodTest==========");
    }


    
public String testMethod(String str, Hashtable ht) throws Exception {
        String returnStr 
= "return str";
        System.out.println(
"begin testMethod invoked");
        System.out.println(
"str= " + str);
        System.out.println(
"name= " + (String) ht.get("name"));
        System.out.println(
"end testMethod invoked");
        
return returnStr;
    }

}



控制台输出如下:
       ===========begin getNameTest============
       string class name: java.lang.String
       button class name: java.awt.Button
       super button class name: java.awt.Component
       clsTest name: java.awt.Button
       ===========end getNameTest============

       ===========begin getMethodTest==========
       begin testMethod invoked......
       str= hello, my dear!
       name= amigo
       end testMethod invoked......
       returnStr= return str
       ===========end getMethodTest==========




在这里,我想说的是如果根据字符串去做我们自己想要的事(包括动态执行对应的方法,生成相应的类),我们在传送数据的时候,大部分都是传字符串的(HTTP,socket)等,我们接受到这些字符串时,再根据这些字符串内容而去做相应的事,那是一件非常不错的事,可以远程调用方法(客户端发送指定的字符串,让服务器根据反射去执行对应的方法)。。。事实上,我也曾经做过这样项目,客户端(不是java语言写的)利用socket去呼叫服务器(java写的)方法,同时还可以直接传递参数,这些都是根据java的反射技术实现的。好了,其他的就多说了,我们从最基础的看起吧,下面是一个最基本方法反射

import java.lang.reflect.Method;

public class TestInt 
{
//测试方法
public String test(String name,int i)
{
System.out.println(
"name:" + name);
System.out.println(i);
return "反射成功!";
}


public static void main(String[] args)
{
try
{
//获取class文件,可以Class.for("Test")获取,这样也可以根据字符串生成类啦
Class te = TestInt.class;
Class[] cl 
= new Class[2];
//添加参数类型
cl[0= String.class;
cl[
1= int.class;
System.out.println(
"11111111");
//根据public的方法,以及参数,参数是Class[]形式
Method method = te.getMethod("test", cl);
System.out.println(
"222222222222");
//开始填充参数
Object[] params = new Object[2];
//params[0] = new String("soda");
params[0= new String("soda");
params[
1= new Integer(23);
System.out.println(
"22222222222");
//获取该class的实例
Object obj = te.newInstance();
//进行方法调用
Object result = method.invoke(obj, params);
System.out.println(
"结果:" + result);
}

catch (Exception e)
{
System.out.println(e);
}


}

}

编译执行,可以看到想要的结果,想象一下,把那些字符串变成别的地方传过来的数据:)

再来一个方法中有数组的反射,我研究了一下,有一点点的区别的。大家要仔细看哦




import java.lang.reflect.Method;
//这里我就不做什么解释了,和前面的几乎一样,大家也可以自己去查查api,Class类的api
public class Test 
{
public void test(double[] dou)
{
System.out.println(dou.length);
System.out.println(dou[
0]);
}

public static void main(String[] args) throws Exception
{
try
{
Class[] cl 
= new Class[1];
cl[
0= double[].class;
System.out.println(
"cl[0]:" + cl[0]);
Object[] in 
= new Object[1];
//注意这里,不是Double[],而是double[]。这里不能用对象数组
double[] db = new double[1];
db[
0= 100.0;
in[
0= db;
Class te 
= Test.class;
Method method 
= te.getMethod("test", cl);
Object obj 
= te.newInstance();
Object objs 
= method.invoke(obj, in);
}

catch (Exception e)
{
System.out.println(e);
}


}

}



好了,基本的是这样了,再复杂的程序也是有基础演变而来的。我在这里就学会许多:)


练习代码:

import java.lang.reflect.*;

class MyClass {
  
  
public String s;
  
  
public MyClass(String s) {
    System.out.println(
"MyClass Constructor");
    
this.s = s;
  }

  
  
public String getS() return s; }
  
public void setS(String s) this.s = s; }
  
  
public static void print(MyClass o) { System.out.println(o); }
}


public class Program {

  
public static void main(String[] args) {
    
try
    
{
      
// 获取类型
      Class myClass = Class.forName("MyClass");
      
      
// 操作构造方法创建对象实例
      Constructor ctor = myClass.getConstructor(new Class[]{String.class});
      Object o 
= ctor.newInstance(new Object[]{"abc"});
      
      
// 操作实例方法 getS
      Method getS = myClass.getMethod("getS"null);
      Object s 
= getS.invoke(o, null);
      System.out.println(
"S=" + s);
      
      
// 操作实例方法 setS
      Method setS = myClass.getMethod("setS"new Class[]{String.class});
      setS.invoke(o, 
new Object[]{"123456789"});
      
      
// 操作字段 s
      Field fs = myClass.getField("s");
      System.out.println(
"Field s=" + fs.get(o));
      fs.set(o, 
"xxxxxx");
      
      
// 操作静态方法 Print
      Method print = myClass.getMethod("print"new Class[]{myClass});
      print.invoke(
nullnew Object[]{o});
      
    }

    
catch (Exception e)
    
{
      System.out.println(e);
    }

  }

}


输出:
MyClass Constructor...
S=abc
Field s=123456789
MyClass@d9f9c3



2. instanceof

instanceof 用来判断类型。除了 instanceof 关键字以外,还可以使用 Class.isInstance() 方法,两者功能相同。
public class Program {

  
public static void main(String[] args) {
    Program o 
= null;
    System.out.println(o 
instanceof Program);
    
    Program o1 
= new Program();
    System.out.println(o1 
instanceof Program);
    System.out.println(Program.
class.isInstance(o1));
  }

}


输出
false
true
true