------- 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 stub Test t1 = new Test(2, 3); String propertyName = "x"; // 内省操作 Object retVal = getProperty(t1, propertyName); System.out.println(retVal);// 2 Object value = 7; setProperties(t1, propertyName, value); System.out.println(t1.getX());// 7 // 使用Beanutils包操作javaBean System.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.Integer System.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; @ItheimaAnntion 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);// 打印 } } }
五.为注解增加基本属性
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());// GREEN System.out.println(annotation.annotationAttr().value()); // itheima } } }