设为首页 加入收藏

TOP

Java反射机制浅析(一)
2015-11-10 13:45:41 来源: 作者: 【 】 浏览:15
Tags:Java 反射 机制 浅析

概念
  Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


  Class类与java.lang.reflect类库一起对反射的概念进行了支持,该类库包含了Field、Method以及Constructor类(每个类都实现了Member接口)。这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。这样开发人员就可以使用Constructor创建新的对象,用get()和set()方法读取和修改与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。另外,还可以调用getFields()、getMethods()、getConstructors()等很便利的方法,以返回表示字段、方法以及构造器的对象的数组。这样,匿名对象的类信息就能在运行时被完全确认下来,而在编译时不需要知道任何事情。


Class?


  类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译一个新类,就会产生一个Class对象(更恰当地说,是被保存在一个同名的.class文件中),它包含了与类有关的信息。为了生成这个类的对象,运行这个对象的虚拟机(JVM)将使用被称为“类加载器(ClassLoader)”的子系统。下面测试类的一些最基本信息。


public class ClassInfo {
?
? ? /**
? ? * @description 输出不同格式类名
? ? * @param clazz
? ? */
? ? public static void printName(Class clazz) {
? ? ? ? System.out.println("getName: " + clazz.getName());
? ? ? ? System.out.println("getCanonicalName: " + clazz.getCanonicalName());
? ? ? ? System.out.println("getSimpleName: " + clazz.getSimpleName());
? ? }
? ?
? ? /**
? ? * @description 输出类的父类和接口
? ? * @param clazz
? ? */
? ? public static void printClassIntf(Class clazz) {
? ? ? ? Class superClass = clazz.getSuperclass();
? ? ? ? Class[] interfaces = clazz.getInterfaces();
? ? ? ? if(superClass != null) {
? ? ? ? ? ? System.out.print(clazz.getSimpleName() + " extends " + superClass.getSimpleName());
? ? ? ? }
? ? ? ? if(interfaces.length > 0) {
? ? ? ? ? ? System.out.print(" implements ");
? ? ? ? ? ? for(int i = 0; i < interfaces.length - 1; i++) {
? ? ? ? ? ? ? ? System.out.print(interfaces[i].getSimpleName() + ", ");
? ? ? ? ? ? }
? ? ? ? ? ? System.out.println(interfaces[interfaces.length - 1].getSimpleName());
? ? ? ? }
? ? }
}


测试类 测试用例:ArrayList


import org.junit.After;
import org.junit.Before;
import org.junit.Test;
?
public class ClassInfoTest {
? ?
? ? private Class clazz;
? ?
? ? private String className = "java.util.ArrayList";
? ?
? ? /**
? ? * forName()是获取Class对象的引用的一种方法。
? ? * 它是用一个包含目标类的文本名的String作输入参数,返回的是一个Class对象的引用。
? ? */
? ? @Before
? ? public void before() {
? ? ? ? try {
? ? ? ? ? ? clazz = Class.forName(className);
? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
? ?
? ? @After
? ? public void after() {
? ? ? ? clazz = null;
? ? }
? ?
? ? @Test
? ? public void testGetName() {
? ? ? ? ClassInfo.printName(clazz);
? ? }
? ?
? ? @Test
? ? public void testPrintClassIntf() {
? ? ? ? ClassInfo.printClassIntf(clazz);
? ? }
?
}


测试结果


getName: java.util.ArrayList
getCanonicalName: java.util.ArrayList
getSimpleName: ArrayList
ArrayList extends AbstractList implements List, RandomAccess, Cloneable, Serializable


Constructor
  Constructor类是对Java普通类中的构造器的抽象。通过Class类的getConstructors()方法可以取得表示构造器的对象的数组,通过getConstructor(Class... parameterTypes)可以取得指定参数类型的构造器。通过newInstance(Object... initargs)方法可以构建一个实例对象。需要注意的是:newInstance()方法的参数要和getConstructor()方法参数相对应。例如 getConstructor(String.class) --- getInstance("Jack")。


  以下的测试都是假设我们从磁盘上或者网络中获取一个类的字节,得知这个类的包名(reflcet)和类名(Reflect)和相关字段名称和方法名称,并通过热加载已经加载到工程中。


  method.invoke()会在下文Method中讲到。


?待测类


package reflect;
?
/**
?* @description 运行时获取的类
?* @author Administrator
?*/
public class Reflect {
? ?
? ? public int id;
? ? private String name;
? ?
? ? public Reflect() {
? ? ? ? this.name = "Tom";
? ? }
? ?
? ? public Reflect(String name) {
? ? ? ? this.name = name;
? ? }
? ?
? ? public Reflect(int id, String name) {
? ? ? ? this.id = id;
? ? ? ? this.name = name;
? ? }
? ?
? ? public void setName(String name) {
? ? ? ? this.name = name;
? ? }
? ?
? ? public String getName() {
? ? ? ? return

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇JavaScript基本类型及类型转换 下一篇C++基于TCP和UDP的socket通信

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: