【JAVASE笔记】JAVA中的反射机制

《JAVA核心技术卷I》第五章反射笔记

JAVA中能够分析类能力的程序称为反射,可以用来:

1、在运行时分析类的能力

2、在运行时查看对象

3、实现通用的数组操作代码

4、利用Method对象

在程序运行期间,JAVA运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类,虚拟机利用运行时类型信息选择相应的方法执行。保存这些信息的类被称为Class。Object类中的getClass()方法将会返回一个Class类型的实例。

Class的getName()方法可以返回类的名字,如果类在一个包里,包的名字也作为类名的一部分;

Random generator = new Random();
Class c1 = generator.getClass();
String name = c1.getName;

还可以调用静态方法forName()获得类名对应的Class对象

String className = "java.util.Random";
Class c1 = Class.forName(className);

只有在className是类名或接口名时才能够执行,否则,forName方法将抛出一个checkedexception(已检查异常)。

如果T是任意的JAVA类型(或void关键字),T.class将代表匹配的类对象

Class c1 = Random.class;
Class c2 = int.class;
Class c3 = Double[].class;

注意:一个Class对象表示一个类型,而这个类型未必一定是一种类。如int不是类,但int.class是一个Class类型的对象。Class类是一个泛型类。

虚拟机为每个类型管理一个Class对象,因此可以用 == 运算符实现两个类对象的比较。

newInstance()方法可以用来动态地创建一个类的实例,非常有用。

利用反射分析类的能力

在java.lang.reflect包中有三个类Field、Method和Constructor分别用于描述类的域、方法和构造器。三个类都有getName方法来返回项目名称。

一个可以分析传入类名对应类的小例子:

package reflection;

import java.lang.reflect.*;
import java.util.*;


public class ReflectionTest {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		String name;
		if(args.length>0) 
			name=args[0];
		else{
			Scanner in=new Scanner(System.in);
			System.out.println("Enter class name(e.g.java.util.Date):");
			name=in.next();
		}
		
		try {
			Class class1=Class.forName(name);
			Class superClass=class1.getSuperclass();
			String modifiers=Modifier.toString(class1.getModifiers());
			if(modifiers.length()>0)
				System.out.println(modifiers + " ");
			if(superClass != null && superClass != Object.class)
				System.out.println(" extends " + superClass.getName());
			System.out.println("\n{\n");
			//打印所有类的构造器 
			printConstructor(class1);
			System.out.println();
			//打印所有类的方法
			printMethods(class1);
			System.out.println();
			//打印所有类的域
			printFields(class1);
			System.out.println("}");
		} catch (ClassNotFoundException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		System.exit(0);
	}
	//打印类所有的域
	private static void printFields(Class class1) {
		Field[] fields = class1.getDeclaredFields();
		for (Field field : fields) {
			Class type = field.getType();
			String name = field.getName();
			System.out.print(" ");
			String modifiers = Modifier.toString(field.getModifiers());
			if(modifiers.length()>0)
				System.out.print(modifiers + " ");
			System.out.println(type.getName() + " " + name + ";");
		}
		
	}
	//打印类所有的方法
	private static void printMethods(Class class1) {
		Method[] methods=class1.getDeclaredMethods();
		for (Method method : methods) {
			Class reType = method.getReturnType();
			String name = method.getName();			
			System.out.print("  ");
			//打印修饰符,返回类型和方法名
			String modifiers = Modifier.toString(method.getModifiers());
			if(modifiers.length()>0)
				System.out.print(modifiers + " ");
			System.out.print(reType.getName() + " " + name + "(");
			//打印参数类型
			Class[] paramType = method.getParameterTypes();
			for(int j = 0; j < paramType.length; j++){
				if(j > 0)
					System.out.print(", ");
				System.out.print(paramType[j].getName());
			}
			System.out.println(");");
		}
	}
	//打印类所有的构造器
	public static void printConstructor(Class class1) {
		Constructor[] constructors=class1.getDeclaredConstructors();
		for(Constructor constructor : constructors){
			String name=constructor.getName();
			System.out.print("  ");
			String modifiers = Modifier.toString(constructor.getModifiers());
			if(modifiers.length()>0)
				System.out.print(modifiers + " ");
			System.out.print(name + "(");
			//打印参数类型
			Class[] paramTypes = constructor.getParameterTypes();
			for(int j = 0; j < paramTypes.length; j++){
				if(j>0)
					System.out.print(", ");
				System.out.print
				(paramTypes[j].getName());
			}
			System.out.println(");");
		}
	}
}

就分析这个小例子来测试,得到如下结果:

注:

getFields()和getDeclaredFields():

getFields方法将返回一个包含Field对象的数组,这些对象记录了这个类或其超类的公有域。getDeclaredFields方法也将返回包含Field对象的数组,这些对象记录了这个类的全部域。如果类中没有域,或者Class对象描述的是基本类型或数组类型,这些方法将返回一个长度为0的数组。

getMethod()和getDeclaredMethod():

返回包含Method对象的数组:getMethod将返回所有的公有方法,包括从超类继承来的公有方法;getDeclaredMethods返回这个类或接口的全部方法,但不包括由超类继承了的方法。

getConstructor()和getDeclaredConstructors():

返回包含Constructor对象的数组,其中包含了Class对象所描述的类的所有公有构造器(getConstructors)或所有构造器(getDeclaredConstructors)。

getModifiers():

返回一个用于描述构造器、方法或域的修饰符的整数数值(public、static等)。使用Modifier类中的这个方法可以分析这个返回值  (isPublic、isPrivate等)。

getParameterTypes():

返回一个用于描述参数类型的Class对象数组

getReturnType():

返回一个用于描述返回类型的Class对象。

Modifier.toString(int modifiers):

返回对应modifiers中位设置的修饰符的字符串表示。

在运行时使用反射分析对象

setAccessible(boolean flag):

为反射对象设置可访问标志。flag为true表面屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置。

get(Object obj):

返回obj对象中用Field对象表示的域值。

set(Obeject obj,Object newValue):

用一个新值设置Obk对象中的Field对象表示的域。

invoke(Object implicitParameter,Object[] explicitParamenters):

调用这个对象所描述的方法,传递给定参数,并返回方法的返回值。对于静态方法,把null作为隐式参数传递。在使用包装器传递基本类型的值时,基本类型的返回值必须是未包装的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值