黑马程序员——————java中的内省和注解

来源:互联网 发布:脸基尼 知乎 编辑:程序博客网 时间:2024/04/28 15:06

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

内省:

在学习内省之前我们先来看javabean的概念:

JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法

主要用于访问私有的字段,且方法名符合某种命名规则

如果要在两个模块之间

传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例

对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段

来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,

JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量

如果方法名为setId,中文意思即为设置id,如果方法名为getId,中文意思即为获取id,

去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,

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

setId()的属性名  id

setCPU的属性名是CPU

总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,

它根本看不到java类内部的成员变量。

一个符合JavaBean特点的类可以当作普通类

一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了

解和应用JavaBean


javabean有什么具体的好处呢:

1、在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进

行操作。

2、JDK中提供了对

JavaBean进行操作的一些API,这套API就称为内省。如果要你自

己去通过getX方法来

访问私有的x,有一定难度,用内省这套api操作JavaBean比用

普通类的方

式更方便。


在具体的开发中常用

Beanutils工具包,他提供了比java中的内省更方便而且强大的功能


现在我们通过一个例子来感受内省:

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;  
 
public class BeansTest {   
  
   public static void main(String[] args) throws Exception {  
       // TODO Auto-generated method stub  
       Person p = new Person();  
       p.setName("zhangsan");  
         
       String propertiesName = "name";  
        String name = extracted(p, propertiesName);
        System.out.println(name);  
         
       String propertiesAge = "age";  
       int age = 23;  
       SetAge(p, propertiesAge, age);  
         
.        String name1 = BeanUtils.getProperty(p, "name");  
       System.out.println(BeanUtils.getProperty(p, "name").getClass().getName());  
       System.out.println(name1);  
 
       BeanUtils.setProperty(p, "age", 19);  
       System.out.println(p.getAge());   
              
   }  
 
   private static void SetAge(Person p, String propertiesAge, int age)  
           throws IntrospectionException, IllegalAccessException,  
           InvocationTargetException {  
       PropertyDescriptor bp1 = new PropertyDescriptor(propertiesAge, p.getClass());  
       Method methodSetAge = bp1.getWriteMethod();  
       methodSetAge.invoke(p,age);  
       System.out.println(p.getAge()); 
               
   }  
 
   private static String  extracted(Object p, String propertiesName)  
            throws IntrospectionException, IllegalAccessException,  
            InvocationTargetException {  
       /*PropertyDescriptor bp = new PropertyDescriptor(propertiesName, p.getClass());  
            Method methodGetName = bp.getReadMethod();  
       Object readVal = methodGetName.invoke(p);  
       System.out.println(readVal);*/  
         
       BeanInfo beanInfo =  Introspector.getBeanInfo(p.getClass());  
       PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();  
       Object retVal = null;  
       for(PropertyDescriptor pd : pds){  
           if(pd.getName().equals(propertiesName))  
           {  
               Method methodGetX = pd.getReadMethod();  
               retVal = (String)methodGetX.invoke(p);  
               break;  
           }  
       }  
       return (String) retVal;          
         
   }  
 
}  

注解:

1、注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,

      没加,则等于没有某种标记。

  以后,javac编译器,开发工具和其他程

    序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,

    就去干相应的事。

2、标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

3、一个注解相当于一个类。

  JDK中提供的最基本的annotation。 

1)、@SuppressWarning(”deprecation”)--->压制警告

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

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

2)、@Deprecated(过时的方法,对于不再使用的方法,可能别人或别的

      地方有调用这个方法,不能删除完事)

     直接在刚才的类中增加一个方法,并加上@Deprecated标注,在另外

     一个类中调用这个方法。测试一下。

     @SuppressWarnings("deprecation") (用这个可以告诉 程序说,

      我知道调用的方法过时了)

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

     public boolean equals(Reflect other)方法与HashSet结合讲解

    像person类,覆盖父类的equals 和hashCode方法,人家接收的参数

    是Object,人们习惯总是传入自己的对象,造成覆盖失败,变成重载!


现在我么看自定义注解:

@Retention(RetentionPolicy.RUNTIME)//告诉jvm这个注解要保存到运行时期  
@Target({ElementType.METHOD,ElementType.TYPE})//告诉编译器,这个注解可以用在方法上,也可以用在类上  
 
public @interface MyAnnotation {  
   String color() default "yellow";//默认缺省值为yellow  
   String value() ;//不指定  
   int [] arrayAttr() default {1,2};//默认为{1,2}  
   EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举类  
   MetaAnnotation annotationAttr() default @MetaAnnotation("xxx");//属性中加注解,用@。可以在对别的类加注解时,改变值

为注解增加基本属性

(可以是八种基本数据类型,String ,数组,枚举,注解,Class)

一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则,就不是。

如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌在增加一个属性来进行区分。

加了属性的标记效果为:

@MyAnnotation(color="red")

定义基本类型的属性和应用属性:

在注解类中增加String color();

@MyAnnotation(color="red")

用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法

MyAnnotation a = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);

System.out.println(a.color());

可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象

如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默

认值或者你只有一个value属性),那么可以省略value=部分,例如:@MyAnnotation("lhm")。

枚举和注解都是特殊的类,不能用new 创建它们的实例对象,创建枚举的实例对象就是在其中增加元素。

在程序中如何创建出一个注解的实例对象啊?直接用@放上一个标记即可.

 import java.lang.reflect.Method;   
 import javax.jws.soap.InitParam; 
@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr=1)  
public class AnnotationTest {     
   @SuppressWarnings("deprecation")  
   @ItcastAnnotation("xyz")  
   public static void main(String[] args) throws Exception{  
       // TODO Auto-generated method stub  
       System.runFinalizersOnExit(true);  
       if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){  
           ItcastAnnotation annotation =     (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);  
           System.out.println(annotation.color());  
           System.out.println(annotation.value());  
           System.out.println(annotation.arrayAttr().length);  
           System.out.println(annotation.lamp().nextLamp().name());  
           System.out.println(annotation.annotationAttr().value());  
       }  
         
        Method mainMethod = AnnotationTest.class.getMethod("main", String[].class);     ItcastAnnotation annotation2 =  
        (ItcastAnnotation)mainMethod.getAnnotation(ItcastAnnotation.class);  
//获取String类上main函数上的注解  
 
       System.out.println(annotation2.value());  
   }  
 
     
@Deprecated//告诉调用者,这个方法过期了。  
   public static void sayHello()  
   {  
       System.out.println("hello,传智播客");  
   }  
}  
 
      
 
MetaAnnotation注解的定义:  
public @interface MetaAnnotation {  
  String value();  

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




原创粉丝点击