欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java开发笔记(七十八)面向对象的后门——反射

程序员文章站 2022-07-10 09:55:56
作为一门面向对象的编程语言,Java认为一切皆是对象,每个对象都能归属于某个类,甚至每个类均可提取出一种特殊的类型,即Class类型。早在前面介绍多态的时候,就提到每个类都存在独一无二的基因,通过比较实例的类基因与具体类名的类基因,即可分辨某个实例是否属于目标类。例如,若想获取公鸡类的类型,则可通过 ......

作为一门面向对象的编程语言,java认为一切皆是对象,每个对象都能归属于某个类,甚至每个类均可提取出一种特殊的类型,即class类型。早在前面介绍多态的时候,就提到每个类都存在独一无二的基因,通过比较实例的类基因与具体类名的类基因,即可分辨某个实例是否属于目标类。例如,若想获取公鸡类的类型,则可通过“类名.class”得到该类的class对象,详细的获取代码如下所示:

		// 第一种方式:通过“类名.class”获取
		class clsfromclass = cock.class;
		system.out.println("clsfromclass name = " + clsfromclass.getname());

 

相对应的,若想获取公鸡实例的类型,则可通过“实例名.getclass()”得到该实例的class对象,详细的获取代码如下所示:

		// 第二种方式:通过“实例名.getclass()”获取
		cock cock = new cock();
		class clsfrominstance = cock.getclass();
		system.out.println("clsfrominstance name = " + clsfrominstance.getname());

 

既然class也是一种数据类型,那么class对象也能调用该类型的实例方法,比如上面两段例子代码都调用了class的getname方法,该方法返回的是class对象蕴含着的目标类类名,而且是包含完整包路径的类名。假如分别运行前面的两段示例代码,就会依次观察到如下的日志信息,从中可见getname方法确实返回了完整的类名:
clsfromclass name = com.addition.reflect.cock
clsfrominstance name = com.addition.reflect.cock
除了通过“类名.class”或者“实例名.getclass()”获得class对象,甚至还能反向操作,只要提供一个保存完整类名的字符串,即可由该字符串生成目标类的class对象,具体的获取代码格式形如“class.forname("完整类名")”。通过类名字符串获取class对象的代码示例如下,注意需要捕捉forname方法可能扔出的“类型未找到异常”classnotfoundexception:

		// 第三种方式:通过该类的完整路径字符串获取
		try {
			class clsfromstring = class.forname("com.addition.reflect.cock");
			system.out.println("clsfromstring name = " + clsfromstring.getname());
		} catch (classnotfoundexception e) { // 捕捉到类型未找到异常
			e.printstacktrace();
		}

 

上述这种通过字符串反向获得class对象的操作被称为“反射”,仿佛光线照到镜子表面反射回来那样,看起来像是一种逆向操作。只是反射远非逆向操作这么简单,它还洞悉面向对象不为人知的各种奥秘,因此经常出现于一些高级的应用场合。
构成反射技术的基石主要有类型class、字段field、方法method这三个好汉,其中尤以class最为重要,它既是从其它类中提取出来的基因类型,又是一种可以直接访问的普通类型。之所以说class普通,是因为它拥有若干可以被开发者访问的方法,使用体验与其它类型相比并没有什么差异。下面是class常见的方法说明:
equals:判断当前类型是否与目标类型相等。
getdeclaredfields:获得当前类型已声明的所有字段(字段即属性)。
getdeclaredfield:根据指定的字段名称获得对应的字段(字段即属性)。
getdeclaredmethods:获得当前类型已声明的所有方法。
getdeclaredmethod:根据指定的方法名称以及参数类型列表获得对应的方法。
getname:获取当前类型包括包名在内的完整类名。
getpackage:获取当前类型所在的包名。
getsimplename:获取当前类型的类名(不包括包名)。
getsuperclass:获取当前类型的父类类型。
以上的说明文字中,字段指的是field类型,方法指的是method类型,有关它们的详细用法将在后面的文章中加以阐述。



更多java技术文章参见《java开发笔记(序)章节目录