1) 获得类
A. 运用getClass() (每个class都有此函数)
i. String str = "abc";
ii. Class c1 = str.getClass();
B. 运用Class.forName() (static method 最常被使用)
i. Class c1 = Class.forName ("java.lang.String");
ii. Class c2 = Class.forName ("java.awt.Button");
C. 运用 .class 语法
i. Class c1 = String.class;
ii. Class c2 = java.awt.Button.class;
iii. Class c4 = int.class;
iv. Class c5 = int[].class;
D. 运用 TYPE语法 ( primitive wrapper classes 基本数据类型包装类的 TYPE语法)
i. Class c1 = Boolean.TYPE;
Public Field getField
(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
public Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
Public Field
getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
public Field[]
getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
3) 获得方法()
以下四个方法可以获得方法,要参见的是Java.lang.class
public Method
getMethod(String name,
... )
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法
public Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
public Method
getDeclaredMethod(String name,…)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
public Method[]
getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
4) 获取类的构造器
以下四个方法可以获得方法,要参见的是Java.lang.class
public Constructor
getConstructor(Class<?>... )
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
public Constructor<?>[]
getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
Public Constructor
getDeclaredConstructor(Class<?>...)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
public Constructor<?>[]
getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法
示例代码:
import java.lang.reflect.Constructor;
public class TestConstructor {
/**
* @param args
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class classType=Class.forName(args[0]);
Constructor Constructor= classType.getConstructor();
System.out.println(Constructor.toString());
}
}
5) 新建类的实例
调用类的Class对象的newInstance方法
import java.lang.reflect.Constructor;
public class TestConstructor {
/**
* @param args
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class classType=Class.forName(args[0]);
//Constructor Constructor= classType.getConstructor();
Object inst=classType.newInstance();
System.out.println(inst);
}
}
调用默认Constructor对象的newInstance方法
import java.lang.reflect.Constructor;
public class TestConstructor {
/**
* @param args
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class classType=Class.forName(args[0]);
Constructor Constructor= classType.getConstructor();
Object inst=Constructor.newInstance();
System.out.println(inst);
}
}
http://blog.csdn.net/lfsf802/article/details/7239652
用一句话来概括反射就是加载一个运行时才知道的类以及它的完整内部结构。
第二种:在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。
一个生活中常看到的例子有助于理解我们为什么要用Java的反射机制:你进了一家饭店,你不知道他们都有那些菜,要多少钱。那么你第一件事情是干啥“服务员拿个菜单过来”,然后指着菜单说“我要这个,我要那个”。
在JDK中有Reflection API的帮助,它主要说明了什么是Java反射机制,这种反射机制提供了什么样的属性和方法,进一步我们能够知道能够通过它完成什么样的工作。
下面咱就一起看看这部分的API。这些接口和类都位于lang包里。 如图: 接口: 类: 简单介绍一些类和接口的用法。 1) Member成员是一种接口,反映有关单个成员(字段或方法)或构造方法的标识信息
2) InvocationHandler是代理实例的调用处理程序 实现的接口(这个接口的具体用法等到java反射机制剖析4着重介绍)
3) Method提供一个类的方法的信息以及访问类的方法的接口。
示例:
4) Filed提供一个类的域的信息以及访问类的域的接口。 示例:
5) Array 类提供了动态创建和访问 Java 数组的方法。 示例:
6) Proxy提供动态地生成代理类和类实例的静态方法(这个方法在java放射机制剖析4着重介绍)。 其余的类和接口的使用方法详见API 从《java反射机制剖析(一)》的API我们看到了许多接口和类,我们能够通过这些接口做些什么呢?
从上篇API中我们能看到它能够完成下面的这些功能:
1) 获得类 A. 运用getClass() (每个class都有此函数) i. String str = "abc"; ii. Class c1 = str.getClass();
B. 运用Class.forName() (static method 最常被使用) i. Class c1 = Class.forName ("java.lang.String"); ii. Class c2 = Class.forName ("java.awt.Button"); C. 运用 .class 语法 i. Class c1 = String.class; ii. Class c2 = java.awt.Button.class; iii. Class c4 = int.class; iv. Class c5 = int[].class; D. 运用 TYPE语法 ( primitive wrapper classes 基本数据类型包装类的 TYPE语法) i. Class c1 = Boolean.TYPE;
2) 获得属性(这个功能的实例见Java反射机制剖析(2)) 以下四个方法可以获得属性,主要参见的是Java.lang.class
Public Field getField (String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段 public Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段 Public Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段 public Field[] getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
3) 获得方法() 以下四个方法可以获得方法,要参见的是Java.lang.class
public Method getMethod(String name, ... ) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 public Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 public Method getDeclaredMethod(String name,…) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法 public Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
4) 获取类的构造器 以下四个方法可以获得方法,要参见的是Java.lang.class
public Constructor getConstructor(Class<?>... ) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法 public Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法 Public Constructor
getDeclaredConstructor(Class<?>...)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
public Constructor<?>[]
getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法
示例代码:
5) 新建类的实例 调用类的Class对象的newInstance方法
调用默认Constructor对象的newInstance方法
调用带参数Constructor对象的newInstance方法
通过Java反射机制剖析(一)和Java反射机制剖析(二)的学习,已经对反射有了一定的了解,这一篇通过动态代理的例子来进一步学习反射机制。
它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
代理类按照创建时期可以分为两种,静态代理类和动态代理类。 静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 动态代理类:在程序运行时,运用反射机制动态创建而成。
静态代理: 业务接口类:
业务接口实现类:
业务代理类:
客户端类:
运行结果:
动态代理: 业务接口类:
业务接口实现类:
BusinessHandler类:
客户端类:
运行结果:
动态代理类原理(示例代码参见java反射机制剖析(三)) a) 理解上面的动态代理示例流程 b) 代理接口实现类源代码剖析 咱们一起来剖析一下代理实现类($Proxy0)的源代码和整个动态代理的流程。 $Proxy0生成的代码如下:
引入眼帘的是这个代理接口实现类实现了业务类的接口(也就是例子中的UserManager接口),又继承了基类Proxy类; 接着就是构造函数,在构造方法中把BusinessHandler传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值(这里要看Proxy的构造方法); 随后看到的就是这个类重写了Proxy类的Equals、hashCode、toString方法,又实现了业务类接口的方法(即UserManager的test方法),具体重写和实现都是用到的super.h.invoke(即Proxy.h.invoke)这个方法。
简单分析完这个代理接口实现类,咱们下面来整体看一下这个动态代理是怎么实现的:
首先客户端初始化了BusinessHandler类,调用这个类的newProxyInstance(new UserManagerImpl())方法来初始化了上面的代理接口实现类; 接下来代理接口实现类通过构造函数把BusinessHandler传过去(也就是代码中的this),并通过Proxy的构造函数给h赋值; 随后再客户端就能实例化出代理接口实现类$Proxy0,我们把它强制转换为业务实现接口(UserManager)类型的(为什么要强制转换,这里非常有意思,如果不强制转换就会报错,这里很好解释,因为当前的环境根本不会知道这个代理接口实现类$Proxy0既继承Proxy又实现业务实现接口UserManager,但是强制转换成UserManager它是可以做到的,因为当前环境中就有UserManager。这就是反射的厉害之处,可以在运行时动态调用任何一个类并可以使用这个类的具体细节。); 之后当我们调用test方法的时候其实是调用了$Proxy0中的test方法,这个方法的实现是通过Proxy.h的invoke方法实现的(即调用了BusinessHandler.invoke方法); 之后在调用了Method的invoke方法(这时的参数是this,和args)。 这样就调用了UserManagerImpl的对应方法,之后返回给客户端。
到此就完成了整个的调用关系。
反射,反射,程序员的快乐 通过上篇文章对动态代理进行了深度剖析,现在想起来还感觉非常有意思,这里面其实最根本的机制就是反射机制,运行时动态实例化任何一个类,并且调用它的具体细节。现在反看动态代理的示例,其实发现这里最关键的还是在就在Proxy.newProxyInstance(..)方法执行时生成了$Proxy0的内存字节码这一点上,当我们有了内存字节码,我们的反射就会大显威力,这样才有了我们之后的一系列的调用关系。
通过反射机制的分析和动态代理示例的剖析,发现编程是一件多么有意思的事情,以至于我们沉浸其中不能自拔。
最后总结一下:反射,反射,程序员的快乐!