`
goalietang
  • 浏览: 25936 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

浅谈Java的反射(四) 内省的使用

阅读更多
      做了这么久Java程序开发,反射(Reflect)的概念倒是知道了不少,可是还有一种方式是跟反射有紧密联系的,我们平时很少谈及到,这就是内省(Introspector)了。

      那什么是内省呢?

      内省(Introspector)是Java 语言对Bean类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。

      Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则,这些 API 存放于包 java.beans 中,一般的做法是通过类 Introspector 的 getBeanInfo方法 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。

      在讲解内省的使用之前,我们首先要了解一个概念,就是一个JavaBean中怎么计算他有多少个属性。

      在java语法里面,一个JavaBean的属性不是看他有多少个字段,而是看他的getter和setter方法的数量,我们在User类里面设置了多个字段,代码如下:
	private String userName;
	private String password;
	private int age;
	private boolean isFemale;


      但是如果我们不为这些字段设置任何setter和getter方法的话,java语言默认为该类没有任何属性(其实还有一个属性,是继承于Object类的Class属性,因为Object为Class属性设置了getClass()的方法。)

      相反,如果User类没有一个字段,但是却有很多getter和setter方法,那么java会计算这些getter和setter的数量来确定有多少属性(一般getter和setter方法是成对的,所以一对算一个属性,但是也可以只存在getter或者setter单个方法,这样单个也算一个属性),我们来看下面的这个叫做Dinner的JavaBean。
public class Dinner {
	
	private String rice;
	private String water;

	public String getEgg() {
		return "egg";
	}
	public void setEgg(String egg) {}
	public String getMilk() {
		return "milk";
	}
	public void setMilk(String milk) {}
	public void setBread(String bread) {}
	public String getCake() {
		return "cake";
	}
	private String getWater() {
		return "water";
	}
	private void setWater(String water) {}
}

      我们可以看到,这个bean里面有个字段rice,但是rice是没有getter和setter方法的,所以不能算Dinner类的属性,egg和milk既有getter方法也有setter方法。而bread只有setter方法,Cake只有get方法,他们都算Dinner类的属性。
      这里面还有个很特别的Water,是私有的方法,也有一个相应的字段叫water(这里大家很容易混淆,但是私有方法再神似也不能叫getter和setter方法,所以water不能算Dinner类的属性)。最后我们运行内省来查看所有属性名称,结果如下:
	//这段代码就是使用内省来获得一个类里面的所有属性的,稍后我们会具体介绍。
	public void findDinnerProperties() throws IntrospectionException{
		//通过Introspector获取一个类的BeanInfo,这个BeanInfo就是该类所有属性的集合
		BeanInfo info = Introspector.getBeanInfo(Dinner.class, Object.class);
		//通过BeanInfo获取PropertyDescriptor,就是属性描述器,描述具体每个属性
		PropertyDescriptor[] pds = info.getPropertyDescriptors();
		//foreach遍历获得每个属性的名字。
		for (PropertyDescriptor pd : pds) {
			System.out.println(pd.getName());
		}
	}

引用
result:
bread
cake
egg
milk

      可见,egg milk虽然没有字段,但是setter和getter方法都有,所以属性描述器就认为他们是Dinner类的属性,bread只有setter方法,而cake只有getter方法,但是属性描述器也认为他们两个都是Dinner类的属性。

      现在让我们来看以下的代码,以便于我们更容易的了解内省的使用方法。他跟反射的使用方法有异曲同工的作用。

//让我们在第一个方法中了解到以上我们所说的获取BeanInfo和PropertyDescriptor的步骤
	@Test
	public void useInspector() throws IntrospectionException{
		//通过Introspector获取一个类的BeanInfo,这个BeanInfo就是该类所有属性的集合,本来只需要一个参数,就是User类的class,第二个参数说明需要排除从Object类中继承而来的所有属性。
		BeanInfo info = Introspector.getBeanInfo(User.class, Object.class);
		//通过BeanInfo获取PropertyDescriptor,就是属性描述器,描述具体每个属性
		PropertyDescriptor[] pds = info.getPropertyDescriptors();
		//foreach遍历获得每个属性的名字。
		for (PropertyDescriptor pd : pds) {
			System.out.println(pd.getName());
		}
	}
//第二个方法是使用内省来获取getter和setter方法的案例。当我们获得了getter和setter方法后,表示我们已经能够正常获得方法对应的属性了。
	@Test
	public void usePropertyDescriptor() throws Exception{
		//通过反射获得一个user对象,以便于之后使用该对象调用方法
		Class clazz = Class.forName("com.ncs.tang.User");
		User user = (User) clazz.newInstance();
		
		//使用PropertyDescriptor对象来获取User类里面的一个属性field4
		PropertyDescriptor pd = new PropertyDescriptor("field4", User.class);
		
		//获得对象的写属性来调用set方法为属性赋值
		Method mw = pd.getWriteMethod();
		mw.invoke(user, 17.5f);
        //获得对象的读属性来调用get方法获取值
		Method mr = pd.getReadMethod();
		System.out.println(mr.invoke(user));
		
		//获取相应属性的类型(Class)
		System.out.println(pd.getPropertyType());
	}
分享到:
评论

相关推荐

    Java反射与内省-PPT

    Java反射与内省是Java编程语言中的核心特性,它们为开发者提供了强大的能力,可以在运行时检查和操作类、接口、对象及其属性。本PPT深入探讨了这些概念,旨在帮助开发者充分利用Java平台的灵活性。 首先,Java反射...

    java反射全解(反射原理+反射API详解+反射与数组+反射与泛型+反射源码与性能开销+反射优缺点+反射与内省)

    要想使用反射,首先需要获得待操作的类所对应的 Class 对象。java.lang.Class 是所有反射 API 的入口点。通过 Class 对象,可以获悉整个类的结构,包括其modifiers、superclass、实现的 interfaces、fields 和 ...

    候捷谈Java反射机制

    3. 测试工具:JUnit等测试框架使用反射来访问私有方法或字段,以便进行单元测试。 4. 通用代码:反射可以帮助编写通用的工具类,这些类能在不了解具体类的情况下处理对象。 然而,反射也带来了一些潜在的问题,如...

    Java中的内省与反射.doc

    ### Java中的内省与反射详解 #### 一、引言 在深入了解Java语言的过程中,我们会遇到两个重要的概念:反射和内省。这两种技术在实际开发中有着广泛的应用,尤其是在需要进行动态操作或元数据处理的场景下尤为重要...

    用反射和内省技术实现简单SpringIOC

    2. 使用反射创建Bean实例。 3. 通过内省技术进行属性注入。 4. 实现Bean的生命周期管理,如初始化、销毁方法的调用。 这样的实现虽然简单,但已经能体现出Spring IoC的基本思想。在实际的Spring框架中,这个过程...

    java内省思维导图

    特别详细的java内省思维导图,全方面介绍java内省的功能以及用法用处。

    JAVA的内省机制(introspector)与反射机制(reflection).docx

    例如,在某个 Bean 中,我们可以使用内省机制来获取某个属性的 getter/setter 方法,然后使用反射机制来调用这些方法。 四、示例代码 下面是一个使用内省机制和反射机制的示例代码: ```java package MyTest; ...

    java反射机制.pdf

    #### 四、Java反射机制的核心类 Java反射机制主要依赖于以下核心类: - `java.lang.Class`:表示一个类或接口的信息,是反射机制的起点。 - `java.lang.reflect.Method`:表示类的方法。 - `java.lang.reflect....

    JAVA反射侯捷观点

    Java反射机制是Java被视为动态语言的关键特性之一,它允许程序在运行时...然而,使用反射时需要谨慎,因为它可能会引入安全风险和性能损失。理解反射的工作原理以及何时、如何正确使用它是每个Java开发者必备的技能。

    酷炫javaweb后台系统适合初学者【里面有封装 反射内省等】

    在这个"酷炫javaweb后台系统"中,包含了一些核心的JavaWeb技术和编程理念,如封装、反射和内省等。这些概念是Java编程的重要组成部分,对于理解和构建高效的应用程序至关重要。 首先,让我们来探讨一下"封装"。封装...

    java ioc,aop实现(内省),仿spring功能实现.

    3. 对象实例化:使用反射和内省技术创建对象实例。 4. 依赖注入:根据配置信息,将依赖对象注入到目标对象的属性或构造函数中。 5. AOP实现:创建一个代理类,拦截目标对象的方法调用,添加额外的切面逻辑。 在实现...

    Java Reflection in Action

    Java Reflection in Action这本书通过将具体案例与反射能力相结合,展示出了如何使用反射来完成各种任务。例如,在处理XML数据时,可以利用反射机制来动态解析XML文档结构,并映射到相应的对象模型中;在自动化软件...

    4.9反射内省.txt.xmind

    4.9反射内省.txt.xmind

    Java 内省(Introspector)深入理解

    Java内省(Introspector)是Java语言提供的一种机制,用于在运行时分析Java对象的属性、方法和事件。这个特性对于开发人员来说非常有用,因为它允许程序动态地检查和修改对象的状态,而不必了解对象的具体实现细节。...

    浅谈初中思想品德教学中的启迪与内省

    【标题】: 初中思想品德教学的启迪与内省策略探究 【描述】: 本文探讨了在初中思想品德教学中如何通过启迪和内省促进学生的道德成长,强调了教学内容与学生生活的关联,以及关注学生个性心理特征的重要性。 【标签...

Global site tag (gtag.js) - Google Analytics