黑马程序员 java_高新技术(三)_内省 JavaBean 注解

来源:互联网 发布:sql server 2008 价格 编辑:程序博客网 时间:2024/05/07 08:23

-------android培训 、java培训、期待与您交流! ----------

1 什么是javaBean

 JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要是用于访问私有字段,且方法名符合某种命名规则.

2 javaBean有什么作用

       如果要在两个模块之间传递多个信息,可以讲这些信息封装到一个javaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object 建成VO)。这些信息在类中用私有字段来存数,想要获取这些信息可以通过一定的方法来获取。

3 如何获取JavaBean中的信息

       JavaBean中的属性是根据其中的getter和setter方法确定的,并不是根据其中的成员变量,如果方法名为setId,中文意思即为设置ID,至于把它存在哪个变量上,无所谓都是表示设置ID 同样如果方法名字为getID 中文意思即为获取ID至于从哪个变量上去,无所谓都是表示取ID,一般按照如下规则命名 去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的

如setId()àid; isLast()àlast;  setCPU—>CPU;      getupsàUPS;

总之一个类被当做javabean使用时,javaBean的属性石根据方法名推断出来的,它根本看不到Java类内部的成员变量

4     JavaBean的好处

       在JavaEE开发中,经常要使用JavaBean,很多环境就要求按JavaBean方式进行操作,主流。

       JDK中提供了对JavaBean进行操作的一些API,这些API就称为内省,如果要你自己去通过getX 方法来访问私有的X是由一定难度的,用内省这套API操作JavaBean比普通类的方式要方便。

 5示例对JavaBean的操作

package cn.itheima.fanshe;import java.beans.PropertyDescriptor;import java.lang.reflect.Method;public class beantest {public static void main(String[] args) throws Exception{//通过bean方式获取对象 rd1的name值RoleDemo rd1 = new RoleDemo("张三","type1");//定义一个要获取的属性名 这个是nameString propertyName = "name";//获取属性 参数 指定要获取的属性,和指定的类PropertyDescriptor pd = new PropertyDescriptor(propertyName,rd1.getClass());//得到属性了 进一步就可以得到属性的get set方法 如下即可得到了X属性的读方法Method methodgname = pd.getReadMethod();//有了这个属性的读方法我们就可以用这个方法在rd1方法上调用。Object retval   = methodgname.invoke(rd1);System.out.println(retval);//输出 调用了带两个属性的构造器 张三Method methodsname = pd.getWriteMethod();//有了这个属性的读方法我们就可以用这个方法在rd1方法上调用。Object retval1   = methodsname.invoke(rd1,"李四");System.out.println(rd1.getName());//输出 李四}}

可以到上面获取属性值的时候有代码复用,那么可以抽取出来构成一个方法,用的时候调用即可

package cn.itheima.fanshe;import java.beans.IntrospectionException;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class beantest {public static void main(String[] args) throws Exception{//通过bean方式获取对象 rd1的name值RoleDemo rd1 = new RoleDemo("张三","type1");//定义一个要获取的属性名 这个是nameString propertyName = "name";Object retval = getProperty(rd1, propertyName);System.out.println(retval);Object newVal = "李四";//输出 调用了带两个属性的构造器 张三getProperts(rd1, propertyName, newVal);System.out.println(rd1.getName());//输出 李四}private static void getProperts(Object rd1, String propertyName,Object newVal) throws IntrospectionException,IllegalAccessException, InvocationTargetException {PropertyDescriptor pd = new PropertyDescriptor(propertyName,rd1.getClass());Method methodsname = pd.getWriteMethod();Object retval1   = methodsname.invoke(rd1,newVal);}//重构的方法private static Object getProperty(Object rd1, String propertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {PropertyDescriptor pd = new PropertyDescriptor(propertyName,rd1.getClass());Method methodgname = pd.getReadMethod();Object retval   = methodgname.invoke(rd1);return retval;}}

对JavaBean的复杂内省操作:在IntroSpector类中有getBeanInfo(Class cls)的方法。

获取Class对象的Bean信息,返回的是BeanInfo类型。

BeanInfo类中有getPropertyDescriptors()的方法,可获取所有的BeanInfo的属性信息,返回一个PropertyDescriptor[]。

在通过遍历的形式,找出与自己想要的那个属性信息。

如:改写get方法:

...BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());          PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();          Object value = null;          for(PropertyDescriptor pd : pds){              if(pd.getName().equals(propertyName)){                  Method methodGetX = pd.getReadMethod();                  value = methodGetX.invoke(pt1);                  break;              }          }  …  

6    Beanutils工具包

       为了便于操作JavaBean,前辈们就编写了BeanUtils包,里面封装了很多对JavaBean的操作,我们在用的时候可以直接拿过来用。

好处是什么呢有如下三个好处

       一提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串形式发送至服务器上的,所以操作的都是字符串。也就是说,这个工具包的内部有自动将证书转换为字符串的操作

       一是支持属性的级联操作,即支持属性链,如果可以设置,人的脑袋上的眼睛的眼珠的颜色。这种级联属性的属性链如果用自己反射,那就很困难了通过这个工具包就可以轻松调用。

       一是 可以和Map集合进行相互转换,可以讲属性信息通过键值对的形式作为Map集合存储(通过staticJava.util.Mapdecribe(java.lang.Objectbean)的方法)也可以讲Map集合转换为JavaBean中的属性信息,(通过static void populate(java.lang.object bean,java.util.map properties)的方法)。

上面我们介绍了通过bean方式获取对象 rd1的name值的方法,下面我们可以利用BeanUtils包简化操作

//通过bean方式获取对象 rd1的name值RoleDemo rd1 = new RoleDemo("张三","type1");//定义一个要获取的属性名 这个是nameString propertyName = "name";System.out.println(BeanUtils.getProperty(rd1, propertyName));BeanUtils.setProperty(rd1, propertyName, "李四");System.out.println(rd1.getName());输出张三 李四 显然简化了操作

注解

java提供的几个基本注解

1、  @suppressWarning(“deprecation”)à压制警告

       suppressWaring是告知编译器或开发工具等提示指定的编译器警告

       deprecation 是告知具体的信息即方法已过时

2、  @Deprecatedà提示成员已经过时,不再推荐使用。

       源代码标记@Deprecated是在JDK1.5中作为内置的annotatin引入的,用于表明类、方法、字段已经不再推荐使用,并且在以后的JDK版本中,可能将其删除,在编译器在默认情况下检测到此标记时,会提示警告信息:假如之前的某个类升级了,其中的某个方法已经过时了,不能够将过时的方法删除,因为可能会影响到调用此类的这个方法的某些程序,这是就可以通过在方法上加这个注解。

3、@Overrideà提示覆盖(父类方法)

加上此注解,可对自己类中的方法判断是否是要覆盖的父类的方法,典型的例子即在集合中覆盖equals(Object obj)方法,其中的参数类型必须是Object,才能被覆盖,若不是,加上此注解就会提示警告。

总结

       注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后javac编译器,开发工具盒其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记就去干相应的事,标记可以加在包,类,字段,方法,方法的参数上以及局部变量上

4、  自定义注解

      自定义注解和接口差不都 ,只是在interface前面加一个@

public @interface Myannotation {} 这个代码是一个最简单的注解,这个注解没有属性,也可以理解为是一个标记注解。就像Serlializable接口一样是一个标记接口,里面未定义方法。也可以再里面加上方法public @interface MyAnnotation{String value() }

       使用子低昂一注解

       @MyAnnotation(“abc”)

       publicvoid myMethod(){}

这里的abc传给了Value 有个规定就是如果没有属性名称的值,而这个注解有有Value属性,就将这个值赋给Value属性,如果没有,就出现编译错误。

 

在使用的时候出了可以省略属性值,还可以使用默认值

public @interface MyAnnotation{public String MyMethod() default “abc”;}//使用默认值@MyAnnotationpublic void MyMethod(){}

5、  对注解进行注解

       为注解提供的注解叫做 元注解  这种注解主要是 Target Retention Documented 和 Inherited

1)  Target

target表示目标,这个注解在用的时候是与某一些目标相关的。看如下示例

 @Target({ElementType.METHOD})@interface MyAnnotation{}@MyAnnotation //放在类上面是错误的public class Class1{@MyAnnotationpublic void myMethod1(){}}

上面这段代码定义了一个注解MyAnnotation和一个类Class1,使用MyAnnotation分别对Class1和myMethod1进行注解,编译这段代码是无法通过的,因为@Target({ElementType.METHOD})

指定了使用注解的目标是一个方法而不是其他任何语句元素。。由此看见,target所指定的目标就是java中的语句元素,比如类,接口,方法等。 比如只可以对方法和构造函数进行注解可以写成

@Target({ElementType.METHOD,ElementType.CONSTRUCTOR})

@interfaceMyAnnotation{}

2)  Retention

注解只有在被保存到class文件中才可以被读出来,Retention就是为设置注解是否保存在class文件中而存在的。详细用法如下

//不将注解保存在class文件中,类似 // 一样在编译时被过滤掉

@Retention(RetentionPolicy.SOURCE)

@interface MyAnnotation1{}

//只将注解保存在class文件中,在运用反射读取注解时忽略掉这些注解。

@Retention(RetentionPolicy.CLASS)

@interface MyAnnotation2{}

//将注解保存在class文件中,通过反射也可以读出注解

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation3{}

3)  Documented

这个注解跟文档有关,在默认的情况下使用javadoc自动生成文档时,直接将被忽略掉,如果想在文档中包含注解那必须使用Documented为文档注释,例如


@interface MyAnnotation{ }@MyAnnotationclass Class1{        public void myMethod() { }}

在使用的javadoc为这段代码生成文档时并不将@MyAnnotation包含进去。生成的文档对Class1的描述为 class Class1 extends java.lang.Object

如果这样定义MyAnnotation将会出现另一个结果。

@Documented

@interface MyAnnotation{}

生成文档为

@MyAnnotation

class Class1 extendsjava.lang.Object

4)  Inherited

  这个是关于继承方面的元注解,不向protected和public成员都将被子类继承一样,在默认的情况下,父类的注解并不会被子类继承,如果要继承,就必须加上Inherited

@Inherited@interface MyAnnotation { }@MyAnnotationpublic class ParentClass {}public class ChildClass extends ParentClass { }在以上代码中ChildClass和ParentClass一样都已被MyAnnotation注解了。

6、  通过反射查看注解

       在JDK1.5以后可以通过反射来获取注解了。之前的版本是不可以的。

       想要得到某一个类或接口的租借信息,可以使用下面代码

       Annotationannotation = AnnotationTest.calss.getAnnotation(MyAnnotation.class);

       想要得到全部的注解信息可以用如下方式

       //包括继承的所有注解

       Annotation[]annotations =AnnotationTest.class.getAnnotations();

//不包括继承的所有注解

Annotation[] anntations     = AnnotationTest.class.getDeclaredAnnotations()

 

-------android培训 、java培训、期待与您交流! ----------



原创粉丝点击