黑马程序员_内省 注解

来源:互联网 发布:plc编程的方法 编辑:程序博客网 时间:2024/05/17 07:19

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

 

一.内省(IntroSpector)

一.内省                        

   1.内省的作用:主要用于操作JavaBean。     

二.javaBean

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

      些方法符合某种命名规则,则可以把它当作JavaBean来使用。

    2.作用:

     如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这 

      些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。

    3.JavaBean的属性

     JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是

     小写的,则把剩余部分的首字母改成小的。

            setId()的属性名id

            isLast()的属性名last

           setCPU的属性名CPU

           getUPS的属性名UPS

      一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。

   4.javaBean的好处:

      一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处:

       a.在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!

       b.JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,有一定难度。用内省这套api操作

          JavaBean比用普通类的方式更方便。

三.对JavaBean的复杂内省操作

   1.BeanInfo

    采用遍历BeanInfo的所有属性方式来查找和设置某个类对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法, 得到的

    BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

  2.Beanutils工具包

   主要用来读取和设置javabean的属性。

    好处:

   将javaBean中的set和get属性值当做字符串操作,但是javaBean中的属性值并不是字符串,该工具包可以完成自动转换。

   支持属性链操作。

  注意:

      在使用Beanutils工具包时,首先需要将commons-loggings.jar

      和Beanutils.jar包添加到工程中,否则会报错。

  3. Proeprtyutils类(该类存在于Beanutils包中)

       该类以属性本身的类型操作,不涉及转换。

  综合示例代码:

package com.itheima.Introspector;import java.beans.BeanInfo;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.PropertyUtils;public class IntrosPectorTest {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubTest t1 = new Test(2, 3);String propertyName = "x";// 内省操作Object retVal = getProperty(t1, propertyName);System.out.println(retVal);// 2Object value = 7;setProperties(t1, propertyName, value);System.out.println(t1.getX());// 7// 使用Beanutils包操作javaBeanSystem.out.println(BeanUtils.getProperty(t1, "x"));// 7// Beanutils将set和get属性的值当做字符串操作,实际JavaBean的属性值不是字符串,该工具包可以自动完成转换BeanUtils.setProperty(t1, "x", "9");System.out.println(t1.getX());// 9// Beanutils支持对属性链的操作BeanUtils.setProperty(t1, "birthday.time", "1234");System.out.println(BeanUtils.getProperty(t1, "birthday.time"));// 1234// Propertyutils类以属性本身的属性操作,不涉及转换PropertyUtils.setProperty(t1, "x", 11);System.out.println(PropertyUtils.getProperty(t1,"x").getClass());// class java.lang.IntegerSystem.out.println(PropertyUtils.getProperty(t1, "x"));// 11}//获取并调用setX方法private static void setProperties(Object pt1, String propertyName,Object value2) throws IntrospectionException,IllegalAccessException, InvocationTargetException {Object value = 7;PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());//对象关联Method methodSetX = pd2.getWriteMethod();//得到setX方法methodSetX.invoke(pt1, value);//调用方法}//获取并调用getX方法private static Object getProperty(Object t1, String propertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {/*方式1 * PropertyDescriptor pd=new * PropertyDescriptor(propertyName,pt1.getClass()); Method * methodGetX=pd.getReadMethod(); Object retVal=methodGetX.invoke(t1); *///方式2: 使用Introspector.getBeanInfo()方法BeanInfo beanInfo = Introspector.getBeanInfo(t1.getClass());PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();Object retVal = null;for (PropertyDescriptor pd : pds) {if (pd.getName().equals(propertyName)) {Method methodGetX = pd.getReadMethod();//获得方法retVal = methodGetX.invoke(t1);//调用方法}}return retVal;}}

 

二.注解

一.概述

   1.注解是jdk1.5的一个新特性。

2.注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程

序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以

及局部变量上。

3.格式:@注解名

4.一个注解就是一个类,在使用注解的同时也就是创建了一个实例对象。

 

二.java提供的三个基本注解

1.@SuppressWarnings() 压缩警告  告知编译器或开发工具等不需要再提示指定的警告信息。

2.@Deprecated  标记过时,如果在方法前加上该注解,表示方法以过时。

3.@Override   标记覆盖,在方法前加上该注解,表示方法是在覆盖方法,如果不存在,就会出错。

四.自定义注解及其应用

   1.注解的应用结构图

2.元注解

a.@Retention用于说明注解保留在哪个阶段,即注解的生命周期。

其三种取值:

RetetionPolicy.SOURCE      java源文件

RetetionPolicy.CLASS        class文件

RetetionPolicy.RUNTIME      内存中的字节码

注意:

class文件中不是字节码,只有用类加载器将class文件中的内容加载进内存,类加载器对class文件进行处理,最终得到的二进制内容才是字节码。

加载器把class文件加载到内存的过程中,也有转换。

 

b.@Target:用于说明注解可以用在哪些成分上。Target的默认值为任何元素。可以用数组方式{ElementType.METHOD,ElementType.TYPE}

3.枚举ElementType(程序元素类型)

  此枚举类型的常量提供了 Java 程序中声明的元素的简单分类。这些常量与 Target 元注释类型一起使用,以指定在什么情况下使用注释类型是合法

的。

常量摘要

  ANNOTATION_TYPE    注释类型声明

CONSTRUCTOR         构造方法声明

FIELD           字段声明(包括枚举常量)

LOCAL_VARIABLE      局部变量声明

METHOD           方法声明

PACKAGE           包声明

PARAMETER           参数声明

TYPE           类、接口(包括注释类型)或枚举声明

 4.应用

a.新建一个注解类ItheimaAnntion

  import java.lang.annotation.ElementType;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)//元注解@Target({ElementType.METHOD,ElementType.TYPE})//说明注解可以使用在哪些成分上public @interface ItheimaAnntion {}

 b.应用注解并对注解进行反射操作

 import java.lang.annotation.Annotation;@ItheimaAnntionpublic class AnnotationTest {public static void main(String[] args) {// 判断注解是否存在if (AnnotationTest.class.isAnnotationPresent(ItheimaAnntion.class)) {// 通过反射得到注解的对象ItheimaAnntion annotation = (ItheimaAnntion) AnnotationTest.class.getAnnotation(ItheimaAnntion.class);System.out.println(annotation);// 打印}}}

五.为注解增加基本属性

1.注解的属性:一个注解相当于一个胸牌,但是为了更加细致的区分,就给胸牌在增加一个属性来进行区分。

2.格式:注解很像接口,属性很像方法。

   例如color属性的定义:String color();

3.为属性指定缺省值:

String color() default "yellow";

4.使用

 在创建注解的时候进行设置属性值,例如:@ItheimaAnntion(color="red")

 在取值的时候以方法的形式去调用。 例如:annotation.color()

注意:如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略

value=部分,例如:@ ItheimaAnntion("xxx")。

六.为注解增加高级属性

1.数组类型的属性

int [] arrayAttr()default {1,2,3};

@ ItheimaAnntion (arrayAttr={2,3,4})

如果数组属性中只有一个元素,这时候属性值部分可以省略大括号。

 2.枚举类型的属性

EnumTest.TrafficLamp lamp() ;

@ ItheimaAnntion (lamp=EnumTest.TrafficLamp.GREEN)

3.注解类型的属性:

ItheimaAnntion annotationAttr()default @ ItheimaAnntion ("xxxx");

@ ItheimaAnntion (annotationAttr=@ ItheimaAnntion (“yyy”) )

 4.Class类型的属性:

      Class cls();

     @ItheimaAnntion (cls=String.class)

这里的.class必须是已定义的类,或是已有的字节码对象

 

代码:

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//元注解@Retention(RetentionPolicy.RUNTIME)//说明注解可以使用在哪些成分上@Target({ ElementType.METHOD, ElementType.TYPE })//注解类public @interface ItheimaAnntion {String color() default "red";// color属性并设置默认值String value();// value属性int[] arrayAttr() default { 1, 2, 3 }; // 数组类型的属性EnumTest.TrafficLamp Lamp() default EnumTest.TrafficLamp.RED; // 枚举类型的属性ItheimaAnntion annotationAttr() default @ItheimaAnntion("黑马程序员");// 注解类型的属性} //应用类import java.lang.annotation.Annotation;@ItheimaAnntion(color = "red", arrayAttr = { 3, 4, 5 }, value = "abc", annotationAttr = @ItheimaAnntion("itheima"))public class AnnotationTest {public static void main(String[] args) {// 判断注解是否存在if (AnnotationTest.class.isAnnotationPresent(ItheimaAnntion.class)) {// 通过反射得到注解的对象ItheimaAnntion annotation = (ItheimaAnntion) AnnotationTest.class.getAnnotation(ItheimaAnntion.class);System.out.println(annotation);// 打印System.out.println(annotation.color());// 打印color属性的值System.out.println(annotation.value());// 打印value属性的值System.out.println(annotation.arrayAttr().length);// 打印数组的长度System.out.println(annotation.lamp().nextlamp().name());// GREENSystem.out.println(annotation.annotationAttr().value()); // itheima}}}




 

 

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

                                             
0 0