----------------------android培训、java培训、期待与您交流!
-------------------------------------
反射:
具有动态获取类的信息,以及动态调用类的方法的功能。
一个类中的每个成员都可以用相应的反射API类中的一个实例对象来表示,通过调用Class类中的方法,可以得到这些实例对象。
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
Class中方法: 静态 Class<?> forName(String className)className - 所需类的完全限定名。
返回与带有给定字符串名的类或接口相关联的 Class 对象。
例如,以下代码片段返回命名为 java.lang.Thread 的类的运行时 Class 描述符。
Class t = Class.forName("java.lang.Thread")
调用 forName("X") 将导致命名为 X 的类被初始化。
Java 的反射机制是使其具有动态特性(所谓动态是指在程序运行期间可以改变程序结构和变量类型。)的非常关键的一种机制,也是在JavaBean 中
广泛应用的一种特性。它可以让程序在运行期间加载编译期间不得而知的Class。并可以生成其实例、调用其方法、为其属性赋值。
JAVA的Reflection(反射)机制同样可以在程序运行期间得到 Class 的名称,构造并生成其实例。利用 Reflection 我们可以为 fields(属性)
赋值,调用其 method。
Java 反射相关的API简介:
位于java.lang.reflect包中
--Class类:代表一个类
--Filed类:代表类的成员变量
--Method类:代表类的方法
--Constructor类:代表类的构造方法
--Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法
反射功能:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
强制访问:method.setaccessible(true)
4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)
反射作用:
----运行时生成instance
想生成对象的实体,在反射动态机制中有两种方法,一个针对无变量的构造方法,一个针对带参数的构造方法,,如果想调用带参数的构造方法,就比较的麻
烦,不 能直接调用Class类中的newInstance(),而是调用Constructor类中newInstance()方法,首先准备一个Class[]作为Constructor的参数类型。然
后调用该Class对象的getConstructor()方法获得一个专属的Constructor的对象,最后再准备一个
Object[]作为Constructor对象昂的newInstance(()方法的实参。
在这里需要说明的是 只有两个类拥有newInstance()方法,分别是Class类和Constructor类
Class类中的newInstance()方法是不带参数的,而Constructro类中的newInstance()方法是带参数的
需要提供必要的参数。
1. 一个简单的例子
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[]) {
try {
Class c = Class.forName("java.util.Stack");
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e){
System.err.println(e);
}
}
}
它的结果输出为:
public synchronized java.lang.Object java.util.Stack.pop()
public java.lang.Object java.util.Stack.push(java.lang.Object)
public boolean java.util.Stack.empty()
public synchronized java.lang.Object java.util.Stack.peek()
public synchronized int java.util.Stack.search(java.lang.Object)
列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。
这个程序使用 Class.forName 载入指定的类,然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描
述某个类中单个方法的一个类。
--------
找出类的方法:找出一个类中定义了些什么方法
import java.lang.reflect.*;
public class Method1 {
private int f1(Object p, int x) throws NullPointerException {
if (p == null)
throw new NullPointerException();
return x;
}
public static void main(String args[]) {
try {
Class cls = Class.forName("Method1"); //取得 method1 类的描述
Method methlist[] = cls.getDeclaredMethods(); //调用 getDeclaredMethods 来获取一系列的 Method 对象,它们分别描述了
定义在类中的每一个方法,包括 public 方法、protected 方法、package 方法和 private 方法等。
for (int i = 0; i < methlist.length; i++)
{
Method m = methlist[i]; //取得 Method 对象列表
System.out.println("name = " + m.getName());
System.out.println("decl class = " + m.getDeclaringClass());
Class pvec[] = m.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " " + pvec[j]);
Class evec[] = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j + " " + evec[j]);
System.out.println("return type = " + m.getReturnType());
System.out.println("-----");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
输出的结果如下:
name = f1
decl class = class method1
param #0 class java.lang.Object
param #1 int
exc #0 class java.lang.NullPointerException
return type = int
-----
name = main
decl class = class method1
param #0 class [Ljava.lang.String;
return type = void
获取构造器、字段信息的用法与上述获取方法的用法类似
------------------
根据方法的名称来执行方法
reflection 也可以来做一些其它的事情,比如执行一个指定了名称的方法:
import java.lang.reflect.*;
public class Method2 {
public int add(int a, int b) {
return a + b;
}
public static void main(String args[]) {
try {
Class cls = Class.forName("Method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod("add", partypes); //方法的名称是在程序的运行过程中指定的
Method2 methobj = new Method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = meth.invoke(methobj, arglist);
Integer retval = (Integer) retobj;
System.out.println(retval.intValue());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
上例中,getMethod用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建了相应的Method 对象之后,在正确的对象实例中执行它。执行该
方法的时候,需要提供一个参数列表,这在上例中是分别用了基本类型包装类 37 和 47 的两个 Integer 对象。执行方法的返回的同样是一个 Integer 对象
84。
--------------
改变字段(域)的值:
reflection 的还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它:
import java.lang.reflect.*;
public class Field2 {
public double d;
public static void main(String args[]) {
try {
Class cls = Class.forName("Field2"); //得到字节码
Field fld = cls.getField("d"); //搜索到成员变量d
Field2 f2obj = new Field2();
System.out.println("d = " + f2obj.d);
fld.setDouble(f2obj, 12.34);
System.out.println("d = " + f2obj.d);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
字段 d 的值被变为了 12.34。
--------------------
使用数组,最后一种用法是反射创建的操作数组。数组在 Java 语言中是一种特殊的类类型,一个数组的引用可以赋给 Object 引用:
import java.lang.reflect.*;
public class Array1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls, 10); //创建了 10 个单位长度的 String 数组
Array.set(arr, 5, "this is a test"); //为第 5 个位置的字符串赋值
String s = (String) Array.get(arr, 5);
System.out.println(s); //将这个字符串从数组中取得并打印了出来。
}
catch (Throwable e) {
System.err.println(e);
}
}
}
----------------------android培训、java培训、期待与您交流!
----------------------详细请查看:http://edu.csdn.net/heima(日记必用代码)