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(null, new Object[]{o});
}
catch (Exception e)
{
System.out.println(e);
}
}
}
输出:
MyClass Constructor...
S=abc
Field s=123456789
MyClass@d9f9c3
2. instanceofinstanceof 用来判断类型。除了 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