黑马程序员-----程序员之路_____JavaBean与内省、注解
来源:互联网 发布:淘宝`热带鱼活体 编辑:程序博客网 时间:2024/05/16 04:19
----------android培训、Java培训、期待与您交流!----------
在写之前我先大概介绍以下内省之JavaBean
33.内省Introspector -->JavaBean -->特殊的Java类==>>int getAger();void setAge(int age)
只要有set和get就可以当JavaBean类来操作 JavaBean的属性是根据方法名称来的
class Person{Private int x;Public int getAger(){Return x;}Public void setAge(int age){This.x=age;}}
去掉set和get要将Age---->如果第二个字母是小的就把第一个字母改成小的--->age
gettime---->time
setTime---->time
getCPU----->CUP
JavaBean和Map是可以相互转换的
1.内省概念
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢?JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id,至于你把它存到哪个变量上,用管吗?如果方法名为getId,中文意思即为获取id,至于你从哪个变量上取,用管吗?去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。
setId()的属性名----->id
isLast()的属性名----->last
setCPU的属性名是什么?----->CPU
getUPS的属性名是什么?----->UPS
总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。
一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean!好处如下:
在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!
JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便。
2.内省的简单操作
PropertyDescriptor类
PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
1、getPropertyType(),获得属性的Class对象。
2、getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法。
3、hashCode(),获取对象的哈希值。
4、setReadMethod(Method readMethod),设置用于读取属性值的方法;setWriteMethod(MethodwriteMethod),设置用于写入属性值的方法;
通过属性名获取对应的值,利用反射方法,如下:
ReflectPoint pt1 = new ReflectPoint(7,9); String propertyName = "x";//给一个属性,获取值 PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodGetX = pd.getReadMethod();//Read对应get()方法 Object reValue = methodGetX.invoke(pt1);
给某个属性设置如下:String propertyName2 = "y";//给一个属性,设置值 PropertyDescriptor pd2 = new PropertyDescriptor(propertyName2,pt1.getClass()); Method methodSetY = pd2.getWriteMethod();//Write对应set()方法 methodSetY.invoke(pt1,3);
Introspector类
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。需要导包java.beans.*。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
以下是示例代码:<pre name="code" class="java">package me.test; import java.lang.reflect.*; import java.beans.PropertyDescriptor; public class JavaBeanTest { public static void main(String[] args) throws Exception { IntroSpectorTest t=new IntroSpectorTest(3) ; //创建一个JavaBean对象 String propertyName="x"; //我们对x属性进行内省操作,定义个String类 保存属性名字 PropertyDescriptor pt1=new PropertyDescriptor(propertyName,IntroSpectorTest.class) ; //创建一个 属性描述符类 PropertyDescriptor类 参数是 属性名字和 JavaBean类的字节码 Method m1=pt1.getReadMethod() ; //获得设置方法的映射类其实跟反射差不多,通过属性描述符返回 Method对象 ,这个对象是 getX()方法的映射对象 Object obj=m1.invoke(t); //调用t对象的getX方法,并返回结果 ,结果自动装箱 System.out.println(obj); //打印结果 PropertyDescriptor pt2=new PropertyDescriptor(propertyName,IntroSpectorTest.class); //创建属性描述类 Method m2=pt2.getWriteMethod() ;//获得设置方法 对应的映射对象 m2.invoke(t, 7); //执行 t对象的setX方法 System.out.println(t.getX()); //打印结果 } }</pre><br> <br> <pre></pre> <pre></pre> <pre></pre> <pre></pre>
Alt+Shift+S----》Generate Geters and Setters,创建get()和set()方法。
选择一些代码,右键—》Refactor—》Extract Method,创建一个方法,提高复用性。
直接new一个PropertyDescriptor对象的方式来让大家了解JavaBean API的价值,先用一段代码读取JavaBean的属性,然后再用一段代码设置JavaBean的属性。
演示用eclipse将读取属性和设置属性的流水帐代码分别抽取成方法:
只要调用这个方法,并给这个方法传递了一个对象、属性名和设置值,它就能完成属性修改的功能。
package cn.itcast.day1;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.PropertyUtils;public class IntroSpectorTest {/** * @param args */public static void main(String[] args) throws Exception {
ReflectPoint pt1 = new ReflectPoint(3,5);String propertyName = "x";//"x"-->"X"-->"getX"-->MethodGetX-->//复杂的过程,反射,下面用内省做Object retVal = getProperty(pt1, propertyName);System.out.println(retVal);Object value = 7;setProperties(pt1, propertyName, value);System.out.println(pt1.getX());}private static void setProperties(Object pt1, String propertyName,Object value) throws IntrospectionException,IllegalAccessException, InvocationTargetException {PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());Method methodSetX = pd2.getWriteMethod();methodSetX.invoke(pt1,value);}private static Object getProperty(Object pt1, String propertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {用内省的方式读取javaBean的X属性PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());Method methodGetX = pd.getReadMethod();Object retVal = methodGetX.invoke(pt1);//调用get方法不接收参数,但是有返回值return retVal;}}
对JavaBean的复杂内省操作
将上述的例子的getProperty方法中换一种用内省的方式读取JavaBean的X属性
private static Object getProperty(Object pt1, String propertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {/*用内省的方式读取javaBean的X属性PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());Method methodGetX = pd.getReadMethod();Object retVal = methodGetX.invoke(pt1);//调用get方法不接收参数,但是有返回值*//*得到BeanInfo最好采用“obj.getClass()”方式,而不要采用“类名.class”方式,这样程序更通用。采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。*/BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();Object retVal = null;for(PropertyDescriptor pd : pds){if(pd.getName().equals(propertyName)){Method methodGetX = pd.getReadMethod();retVal = methodGetX.invoke(pt1);break;}}return retVal;}
3、BeanUtils工具包
BeanUtils可以操作JavaBean也可以操作Map
为JavaBean提供更多、放方便的功能。
beanutils.jar = beanutils-core.jar + beanutils-bean-collections.jar,可以通过BuildPath,添加额外的jar包,或者工程下建立lib目录,将jar包复制进来,再加载这个jar包:右键—》add to BuildPath。使用时需要导包:org.apache.commons.beanutils.BeanUtils。
需要配合使用acpche提供的日志包:logging。
获得属性的值,例如,BeanUtils.getProperty(pt1,"x"),返回字符串
设置属性的值,例如,BeanUtils.setProperty(pt1,"y",22),参数是字符串或基本类型自动包装。设置属性的值是字符串,获得的值也是字符串,不是基本类型。
BeanUtils的特点:
1、对基本数据类型的属性的操作:在WEB开发、使用中,录入和显示时,值会被转换成字符串,但底层运算用的是基本类型,这些类型转到动作由BeanUtils自动完成。
2、对引用数据类型的属性的操作:首先在类中必须有对象,不能是null,例如,private Date birthday=new Date();。操作的是对象的属性而不是整个对象,例如,BeanUtils.setProperty(pt1,"birthday.time",121);
Java7的新特性:Map和JavaBean之间可以进行相互转换,key是属性,value是值。
describe:JavaBean—>Map;populate:Map—>JavaBean。例如:
Map map = (name:Kim,age:18);
BeanUtils.setProperty(map,"name","Kim");
copyProperties(Object dest, Objectorig),将一个对象的属性值复制到另一个对象的属性,需要保证属性一致。
PropertyUtils类
和BeanUtils不同在于,运行getProperty、setProperty操作时,没有类型转换,使用属性的原有类型或者包装类。
Introspector类
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。需要导包java.beans.*。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
Introspector类
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。需要导包java.beans.*。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
4.注解Annotation
在注解上加注解称之为元注解
JDK1.5出现的新特性。在java.lang.annotation包中。
对于过时的语句,java会提示过时了,通过@SuppressWarnings("Deprecation")在DOS中取消提示,但Eclipse无法取消。这就是注解,相当于标记。编译器、开发工具、javac通过反射获得注解里的内容,进而明确应该做什么、不应该做什么。注解可以加在包、类、属性、方法、参数及局部变量之上。
一个注解就是一个类。@SuppressWarnings,取消警告。@Deprecated,已过时,老版可以用,新版无法用。
HashSet集合中,对象必须覆盖Object类的equals()方法,否则会继续使用Object类的equals()方法进行比较,错误的比较方法。覆盖equals()方法,参数必须一致,为了防止错误写入本类的对象,加入@Override,必须正确覆盖父类方法,不是创建新方法。
注解的应用
在源程序中,调用一个类,这个类会用到注解,需要先准备好注解类,类在调用注解类的对象。注解类的写法类似接口,@interface。先写好注解类A,将注解放在类B中,类C在调用类B时通过反射获得注解类A的内容,进而明确该做什么、不该做什么。可以加上多个注解,加上的实际是注解类的对象:@interfaceA。
main()方法必须放在一个类下,但与这个类不一定有所属关系。
在注解类A上加注解B,这个注解B只为这个注解类A服务,B称为“元注解”。类似的还有元信息、元数据。元注解有2个:Rentention和Target。对注解类的注解,可以理解为注解类的属性。
Rentention注解类
注解的生命周期:Java源文件—》class文件—》内存中的字节码。编译或者运行时,都有可能会取消注解。Rentention的3种取值意味让注解保留到哪个阶段,RententionPolicy.SOURCE、RententionPolicy.CLASS(默认值)、RententionPolicy.RUNTIME。
@Override、@SuppressWarnings是默认保留到SOURCE阶段;@Deprecated是保留到RUNTIME阶段。
Rentention相当于注解类的一个属性,因为Rentention的值不同,注解类保留到的阶段不同。注解类内部Rentention的值使用value表示,例如,@Deprecated中,value=Runtime。
Rentention的值是枚举RententionPolicy的值,只有3个:SOURCE、CLASS、RUNTIME。
Target注解类
性质和Rentention一样,都是注解类的属性,表示注解类应该在什么位置,对那一块的数据有效。例如,@Target(ElementType.METHOD)
Target内部的值使用枚举ElementType表示,表示的主要位置有:注解、构造方法、属性、局部变量、函数、包、参数和类(默认值)。多个位置使用数组,例如,@Target({ElementType.METHOD,ElementType.TYPE})。
类、接口、枚举、注解这一类事物用TYPE表示,Class的父类,JDK1.5的新特性。
注解的基本属性
属性,给注解提供更加详细的信息。
注解相当于接口,属性相当于方法。例如,@ItcastAnnotation(color="black"),给属性赋值,取值时类似调用方法,例如,System.out.println(annotation.color());。所有的属性必须全部出现,除非有缺省值。
如果只有value属性,没有其他属性,可以不写=,只针对value,例如,@SuppressWarnings("Deprecation")。或者有其他属性而且有缺省值,例如,String color() default "blue";,此时value单独出现,不用=。
获得注解的属性的值,例如:
if(AnnotationDemo.class.isAnnotationPresent(ItcastAnnotation.class)){ItcastAnnotation annotation =(ItcastAnnotation)AnnotationDemo.class.getAnnotation(ItcastAnnotation.class);System.out.println(annotation.color());}}
利用反射获得注解的对象,在让该对象调用属性对应的方法。注意类型转换。
Rentention和Target也是属性,都是value对应的值,值的类型分别是RententionPolicy和ElementType,例如,@Retention(value=RetentionPolicy.RUNTIME)。
注解的高级属性
给注解增加高级属性,数组、枚举、注解。
数组类型的属性
例如,int[] arr() default {3,7,5};,MyAnnotation(arr={3,7,6})。如果数组只有1个元素,可以不加{}。@Target({ElementType.METHOD,ElementType.TYPE})也是数组类型的属性。
枚举类型的属性
//注解类内部的内容EnumerationDemo.TrafficLamp lamp() default EnumerationDemo.TrafficLamp.RED;//调用注解的类上@ItcastAnnotation(lamp=EnumerationDemo.TrafficLamp.YELLOW)//对注解进行操作System.out.println(annotation.lamp().nextLamp().name());
注解类型的属性
将一个注解类作为属性加入到另一个注解类中。MetaAnnotation annotationAtt() default @MetaAnnotation("Jobs")@ItcastAnnotation(annotationAtt=@MetaAnnotation("Kim"))annotation.annotationAtt().value()
5、总结
Web 开发框架 Struts 中的 FormBean 就是通过内省机制来将表单中的数据映射到类的属性上,因此要求 FormBean 的每个属性要有 getter/setter 方法。但也并不总是这样,什么意思呢?就是说对一个 Bean 类来讲,我可以没有属性,但是只要有 getter/setter 方法中的其中一个,那么 Java 的内省机制就会认为存在一个属性,比如类中有方法 setMobile ,那么就认为存在一个 mobile 的属性。
将 Java 的反射以及内省应用到程序设计中去可以大大的提供程序的智能化和可扩展性。有很多项目都是采取这两种技术来实现其核心功能,例如我们前面提到的 Struts ,还有用于处理 XML 文件的 Digester 项目,其实应该说几乎所有的项目都或多或少的采用这两种技术。在实际应用过程中二者要相互结合方能发挥真正的智能化以及高度可扩展性。
-------android培训、java培训、期待与您交流! ----------
- 黑马程序员-----程序员之路_____JavaBean与内省、注解
- 黑马程序员--JAVA之内省、注解与类加载器
- 黑马程序员 内省和注解
- 黑马程序员 高新技术---内省、注解
- 黑马程序员_内省 注解
- 黑马程序员之反射与内省
- 黑马程序员 高新技术<四>--->内省、注解与类加载器
- 黑马程序员-JAVA基础加强-内省与注解
- 黑马程序员_高新技术之内省和注解小结
- 黑马程序员---张老师高新技术之反射,内省及注解
- 黑马程序员--JavaBean与内省
- 黑马程序员-高新技术(内省,注解)
- 黑马程序员——内省和注解
- 黑马程序员_反射、内省、注解
- 黑马程序员_内省和注解
- 黑马程序员----java高新技术--内省,注解
- 黑马程序员_java内省注解泛型
- 黑马程序员_java内省注解泛型
- 沈阳改派怎么办?
- Windows 消息分类
- C#中"浅复制"与"深复制"的区别
- ADB server didn’t ACK解决
- oracle创建用户和找回密码
- 黑马程序员-----程序员之路_____JavaBean与内省、注解
- 阿里巴巴校招算法(黑板50个数字问题)
- 【C语言】02-第一个C程序
- 【C语言】03-第一个C程序代码分析
- 2014校招找工作小结
- 两步教你生成文档目录
- 加载swf并获取swf中的元件
- 【C语言】04-函数
- Eclipse上GIT插件EGIT使用手册