注解

来源:互联网 发布:如果南京是首都知乎 编辑:程序博客网 时间:2024/06/05 20:51

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

//基本的三个注解            @SuppressWarnings("deprecation")  //忽略特定错误            @Deprecated //表示作用的方法已过时。            @Override //表示作用的方法必须覆盖父类,如果我们不小心写错方法了没有覆盖父类的方法编译会帮我们保错,这样可以避免一些bug。注解相当与你的源程序调用了一个类,要在源程序中应用某注解,得先准备好这个注解类。就像你要调用某个类,得先开发出这个类。下面有代码演示这个过程://定义注解类            @interface A            {}            //应用注解类            @A            class B            {}            //对“应用了注解的类”,进行反射操作的类            Class C            {                B.class.isAnnotionPresent(A.class);                A a = B.class.getAnnotion(A.class);            } 元注解:注解的注解。经常看it书会看到元数据,元属性的词,他们的意思是数据的数据,属性的属性。在定义注解的时候需要元注解的作用。// 注解的存在分为三个阶段,源程序---->class文件----->字节码(class文件里的不是字节码,虚拟机加载类后经过转换才产生字节码)           //用@Retention元注解说明定义的注解的生命周期在哪个阶段。默认是保存到class阶段。             // 让定义的注解保持到运行时。            @Retention(RetentionPolicy.RUNTIME)            //注解作用的对象分为,类,方法,包,字段,方法参数及局部变量,可以用@Targer元注解说明            //定义注解可以用在类和方法上,这里ElementType.TYPE的TYPE命名比CLASS更准确,Class,枚举、注解等这些都是类型。            //定义为这个注解可以用在以上这些类型上而不只是类。            @Targer({ElementType.METHOD,ElementType.TYPE})               //为注解添加属性、            @Interface A            {                String color() defualt "blue";            }            //设置注解属性            @A(color="red")

知识点1:注解中属性返回值的类型,不能是普通类类型。只能是:8种基本类型、String、Class、Enum、Annotation和这些类型的数组。
知识点2:使用哈希集合的时候注意添加的对象的类定义equals方法时参数的类型必须是object,因为哈希集合在计算对象哈希值时调用的是这个规格的equals方法,如果一不小心参数类型用本类类型,就会产生一个重载的equals方法,而哈希集合计算哈希值时调用的是参数为object类型的equals这样就调用的是父类object的equals,这样就产生的bug很难被发现。可以在定义这类方法时用@Override注解,帮助我们检测。
张琴看的总结笔记:
元数据:描述数据的结构。注解就是java中源代码的元数据。
一、格式:
@
二、预定义的注解:
@override 覆盖父类
@Deprecated 不建议使用这个类
@ SuppressWarnings 压制警告
都属于java.lang包里面的,所以可以直接使用@java.lang.SuppressWarnings(value={”unchecked”})
(1)自定义的注解:
格式:public @interface demo{}
(2)注解的使用:

@demoPublic class User{}

(3) 给注解添加内容,格式如下:

public @interface demo{//即为给注解添加了一个name属性 public String name();//则在注解被使用的时候默认是得给 注解的属性赋值的。 } 那么当注解使用的时候应该为@demo(name=”test”)Public class User{}

(4)有时候用户不需要提供注解属性的值,那么直接给注解的属性提供一个默认值即可。

public @interface demo{//即为给注解添加了一个name属性 public String name() defualt  "blue";} 

(5)规定注解的用处

//说明只能用在类上面 和方法上面 @Targe({ElementType.METHOD,ElementType.TYPE})  public @interface demo{ public String name() defualt  "blue";//即为给注解添加了一个name属性  } 

ElementType包含:
(1) TYPE: Class interface enum
(2) FIELD(字段):Field
(3) METHOD(方法):Method
(4) PARAMETER(参数):Method parameter
(5) CONSTRUCTOR(构造器):Constructor
(6) 注解的存在分为三个阶段,源程序—->class文件—–>字节码(class文件里的不是字节码,虚拟机加载类后经过转换才产生字节码)
//用@Retention元注解说明定义的注解的生命周期在哪个阶段。默认是保存到class阶段。
// 让定义的注解保持到运行时。
@Retention(RetentionPolicy.RUNTIME)
RetentionPolicy:
(1)SOURCE:源程序
(2)CLASS:class文件
(3)RUNTIME:运行时间
一般默认即可。默认即为RUNTIME
(7)添加公共文档 Documented
在默认情况下在使用javadoc自动生成文档的时候,注解将被忽略掉。如果想要在文档中包含注解,必须使用@ Documented

@ Documented@Retention(RetentionPolicy.RUNTIME) @Targe({ElementType.METHOD,ElementType.TYPE})  public @interface demo{ public String name() defualt  "blue";//即为给注解添加了一个name属性 } 

(8)设置继承@Inherited
在默认情况下,父类的注解并不会被子类继承,如果要继承,就必须要加上Inherited注解。
即为:

@Inherited@ Documented@Retention(RetentionPolicy.RUNTIME) @Targe({ElementType.METHOD,ElementType.TYPE})  public @interface demo{ public String name() defualt  "blue";//即为给注解添加了一个name属性} 

(9)读取注解:
使用反射机制。

Public static main(String[] args){//先将使用注解的类取出来 Class  c =Class.forName(“User”);//获取类的字段Field fs[]=c.getDeclaredFields();//遍历字段For(Filed f:fs){//如果字段使用了demo注解 Boolean flag=f.isAnnotationPresent(demo.class);If(flag){//将注解类取出Demo dm=(demo)c.getAnnotetion(demo.class);//打印注解类的属性值System.out.println(“name:”+dm.name());}}}

PS:[番外]
包 java.lang.annotation 中包含所有定义自定义注解所需用到的原注解和接口。如接口 java.lang.annotation.Annotation 是所有注解继承的接口,并且是自动继承,不需要定义时指定,类似于所有类都自动继承Object。

package com.tmser.annotation;/** * *@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。 *方法的名称就是参数的名称,返回值类型就是参数的类型。 *可以通过default来声明参数的默认值。 *在这里可以看到@Retention和@Target这样的元注解,用来声明注解本身的行为。 *@Retention用来声明注解的保留策略,有CLASS、RUNTIME和SOURCE这三种, *分别表示注解保存在类文件、JVM运行时刻和源代码中。 *只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息。 *@Target用来声明注解可以被添加在哪些类型的元素上,如类型、方法和域等。 *就可以定义一个注解了,它将自动继承Annotation */public @interface TestA {//这里定义了一个空的注解,它能干什么呢。我也不知道,但他能用。}在下面这个程序中使用它:package com.tmser.annotation; import java.util.HashMap;import java.util.Map;/** * 这个类专门用来测试注解使用 * @author tmser */@TestA    //使用了类注解public class UserAnnotation {       @TestA //使用了类成员注解    private Integer age;        @TestA //使用了构造方法注解    public UserAnnotation(){            }    @TestA //使用了类方法注解    public void a(){        @TestA //使用了局部变量注解        Map m = new HashMap(0);    }        public void b(@TestA Integer a){ //使用了方法参数注解           }}

四个元注解分别是:@Target,@Retention,@Documented,@Inherited ,再次强调下元注解是Java API提供,是专门用来定义注解的注解,其作用分别如下。

    @Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括:       ElemenetType.CONSTRUCTOR 构造器声明       ElemenetType.FIELD 域声明(包括 enum 实例)       ElemenetType.LOCAL_VARIABLE 局部变量声明      ElemenetType.ANNOTATION_TYPE 作用于注解量声明      ElemenetType.METHOD 方法声明      ElemenetType.PACKAGE 包声明       ElemenetType.PARAMETER 参数声明       ElemenetType.TYPE 类,接口(包括注解类型)或enum声明   @Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括:       RetentionPolicy.SOURCE 注解将被编译器丢弃       RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃       RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。    @Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。  @Inherited 允许子类继承父类中的注解,例子中补充。

jdk1.5 既然增加了注解,肯定就增加了相关读取的api
在java.lang.reflect包中新增了AnnotatedElement接口,JDK源码如下:

public interface AnnotatedElement {  boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);    <T extends Annotation> T getAnnotation(Class<T> annotationClass);  Annotation[] getAnnotations(); Annotation[] getDeclaredAnnotations();}isAnnotationPresent:判断是否标注了指定注解getAnnotation:获取指定注解,没有则返回nullgetAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组以下函数很重要,即为注解如何使用。package com.tmser.annotation;import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class ParseAnnotation {    /**     * 简单打印出UserAnnotation 类中所使用到的类注解     * 该方法只打印了 Type 类型的注解     * @throws ClassNotFoundException     */    public static void parseTypeAnnotation() throws ClassNotFoundException {          Class clazz = Class.forName("com.tmser.annotation.UserAnnotation");         Annotation[] annotations = clazz.getAnnotations();          for (Annotation annotation : annotations) {              TestA testA = (TestA)annotation;            System.out.println("id= \""+testA.id()+"\"; name= \""+testA.name()+"\"; gid = "+testA.gid());          }      }     /**     * 简单打印出UserAnnotation 类中所使用到的方法注解     * 该方法只打印了 Method 类型的注解     * @throws ClassNotFoundException     */    public static void parseMethodAnnotation(){        Method[] methods = UserAnnotation.class.getDeclaredMethods();          for (Method method : methods) {              /*              * 判断方法中是否有指定注解类型的注解              */              boolean hasAnnotation = method.isAnnotationPresent(TestA.class);              if (hasAnnotation) {                  /*                  * 根据注解类型返回方法的指定类型注解                  */                  TestA annotation = method.getAnnotation(TestA.class);                  System.out.println("method = " + method.getName()                          + " ; id = " + annotation.id() + " ; description = "                          + annotation.name() + "; gid= "+annotation.gid());              }          }      }        /**     * 简单打印出UserAnnotation 类中所使用到的方法注解     * 该方法只打印了 Method 类型的注解     * @throws ClassNotFoundException     */    public static void parseConstructAnnotation(){        Constructor[] constructors = UserAnnotation.class.getConstructors();          for (Constructor constructor : constructors) {             /*              * 判断构造方法中是否有指定注解类型的注解              */              boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class);              if (hasAnnotation) {                  /*                  * 根据注解类型返回方法的指定类型注解                  */                  TestA annotation =(TestA) constructor.getAnnotation(TestA.class);                  System.out.println("constructor = " + constructor.getName()                          + " ; id = " + annotation.id() + " ; description = "                          + annotation.name() + "; gid= "+annotation.gid());              }          }      }    public static void main(String[] args) throws ClassNotFoundException {        parseTypeAnnotation();        parseMethodAnnotation();        parseConstructAnnotation();    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 梦见鬼在梦里怎么办 宝宝晚上奶水不够吃怎么办 十个月晚上奶水不够吃怎么办 产妇晚上奶水不够吃怎么办 刚出生的宝宝不吃母乳怎么办 宝宝六个月奶不够吃怎么办 六个月奶不够吃怎么办 刚出生奶不够吃怎么办 做梦醒了看见鬼怎么办 宝宝到陌生地方哭闹怎么办 大人生病住院小孩没人带怎么办 孕妇被小猫抓了怎么办 怀孕了家里有猫怎么办 厕所被湿纸巾堵了怎么办 5天新生儿不拉屎怎么办 4月宝宝不拉屎怎么办 两岁宝宝晚上睡觉哭闹怎么办 2月婴儿吐奶很多怎么办 心情不好回奶了怎么办 四个月了没奶怎么办 八岁宝宝还尿床怎么办 自己一人在家害怕怎么办 被猫抓伤流血了怎么办 被小狐狸咬了怎么办 怀孕吃了兔子肉怎么办 鸟总在窗子上啄怎么办? 有鸟飞进楼道里怎么办 租的房间房东要求改建怎么办 小偷偷钱抓住不还钱怎么办 损友圈羊被陌生人偷了怎么办 在酒店如果遇到客人偷东西怎么办 梦见家里有不好的东西怎么办 被小孩要破了怎么办啊 租一个房子小孩一进房就哭怎么办 墙缝里有蝙蝠窝怎么办 小蝙蝠在墙缝里怎么办 小孩一进屋就哭怎么办 屋门对着厕所门怎么办 入室门对厨房门怎么办 厕所正对入户门怎么办 小区楼交错冲路怎么办