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