java 注解和 重复注解



1、什么是java注解

Annotation(注解)是JDK5.0及以后版本引入的一个特性。注解是java的一个新的类型(与接口很相似),它与类、接口、枚举是在同一个层次,它们都称作为java的一个类型(TYPE)。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。它的作用非常的多,例如:进行编译检查、生成说明文档、代码分析等。

2.jdk提供的3个基本注解

a.

@SuppressWarnings
该注解的作用是阻止编译器发出某些警告信息。它可以有以下参数:
deprecation:过时的类或方法警告。
unchecked:执行了未检查的转换时警告。
fallthrough:当Switch程序块直接通往下一种情况而没有Break时的警告。path:在类路径、源文件路径等中有不存在的路径时的警告。serial:当在可序列化的类上缺少serialVersionUID定义时的警告。finally:任何finally子句不能完成时的警告。all:关于以上所有情况的警告。

b.

@Deprecated
该注解的作用是标记某个过时的类或方法。

c.
@Override
该注解用在方法前面,用来标识该方法是重写父类的某个方法。

3.注解的生命周期

一个注解可以有三个生命周期,它默认的生命周期是保留在一个CLASS文件,但它也可以由一个@Retetion的元注解指定它的生命周期。

a.java源文件
   当在一个注解类前定义了一个@Retetion(RetentionPolicy.SOURCE)的注解,那么说明该注解只保留在一个源文件当中,当编译器将源文件编译成class文件时,它不会将源文件中定义的注解保留在class文件中。

b.class文件中
   当在一个注解类前定义了一个@Retetion(RetentionPolicy.CLASS)的注解,那么说明该注解只保留在一个class文件当中,当加载class文件到内存时,虚拟机会将注解去掉,从而在程序中不能访问。

c.程序运行期间
   当在一个注解类前定义了一个@Retetion(RetentionPolicy.RUNTIME)的注解,那么说明该注解在程序运行期间都会存在内存当中。此时,我们可以通过反射来获得定义在某个类上的所有注解。

4.元注解
元注解,就是定义注解的注解,也就是说这些元注解是的作用就是专门用来约束其它注解的注解。请区别上面那三个注解,他们也是通过元注解定义而来的。
元注解有哪些呢,主要有四个@Target,@Retention,@Documented,@Inherited

5.自定义注解

1)、定义一个最简单的注解
public @interface MyAnnotation {
    //......
}
2)、把注解加在某个类上:
@MyAnnotation
public class AnnotationTest{
    //......
}
以下为模拟案例
自定义注解@MyAnnotation
package com.ljq.test;

 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;

 /**
 * 定义一个注解
 * 
 * 
 * @author jiqinlin
 *
 */
 //Java中提供了四种元注解,专门负责注解其他的注解,分别如下

 //@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
 //RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉
 //RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)
 //RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息

 //@Target元注解,默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
 //ElementType.CONSTRUCTOR: 构造器声明
 //ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
 //ElementType.LOCAL_VARIABLE: 局部变量声明
 //ElementType.METHOD: 方法声明
 //ElementType.PACKAGE: 包声明
 //ElementType.PARAMETER: 参数声明<pre class="java" name="code">//ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
//ElementType.TYPE: 类、接口(包括注解类型)或enum声明 //@Documented将注解包含在JavaDoc中 //@Inheried允许子类继承父类中的注解 @Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.TYPE}) public @interface MyAnnotation { //为注解添加属性 String color(); String value() default "我是林计钦"; //为属性提供默认值 int[] array() default {1, 2, 3}; Gender gender() default Gender.MAN; //添加一个枚举 MetaAnnotation metaAnnotation() default @MetaAnnotation(birthday="我的出身日期为1988-2-18"); //添加枚举属性 }
 

注解测试类AnnotationTest
package com.ljq.test;

 /**
 * 注解测试类
 * 
 * 
 * @author jiqinlin
 *
 */
 //调用注解并赋值
 @MyAnnotation(metaAnnotation=@MetaAnnotation(birthday = "我的出身日期为1988-2-18"),color="red", array={23, 26})
 public class AnnotationTest {

    public static void main(String[] args) {
        //检查类AnnotationTest是否含有@MyAnnotation注解
         if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
            //若存在就获取注解
             MyAnnotation annotation=(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
            System.out.println(annotation);
            //获取注解属性
             System.out.println(annotation.color()); 
            System.out.println(annotation.value());
            //数组
             int[] arrs=annotation.array();
            for(int arr:arrs){
                System.out.println(arr);
            }
            //枚举
             Gender gender=annotation.gender();
            System.out.println("性别为:"+gender);
            //获取注解属性
             MetaAnnotation meta=annotation.metaAnnotation();
            System.out.println(meta.birthday());
        }
    }
}

枚举类Gender,模拟注解中添加枚举属性
package com.ljq.test;
 /**
 * 枚举,模拟注解中添加枚举属性
 * 
 * @author jiqinlin
 *
 */
 public enum Gender {
    MAN{
        public String getName(){return "男";}
    },
    WOMEN{
        public String getName(){return "女";}
    }; //记得有“;”
     public abstract String getName();
}

注解类MetaAnnotation,模拟注解中添加注解属性
package com.ljq.test;

 /**
 * 定义一个注解,模拟注解中添加注解属性
 * 
 * @author jiqinlin
 *
 */
 public @interface MetaAnnotation {
    String birthday();
}


本文部分内容来自 http://www.cnblogs.com/linjiqin/archive/2011/02/16/1956426.html 为了学习本人收藏,并有些改动

jdk8新特性 重复注解

重复注解机制本身必须用 @Repeatable 注解。事实上,这并不是语言层面上的改变,更多的是编译器的技巧,底层的原理保持不变。让我们看一个快速入门的例子:
package com.javacodegeeks.java8.repeatable.annotations;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
public class RepeatingAnnotations {
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    public @interface Filters {
        Filter[] value();
    }
     
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    @Repeatable( Filters.class )
    public @interface Filter {
        String value();
    };
     
    @Filter( "filter1" )
    @Filter( "filter2" )
    public interface Filterable {       
    }
     
    public static void main(String[] args) {
        for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
            System.out.println( filter.value() );
        }
    }
}

正如我们看到的,这里有个使用@Repeatable( Filters.class )注解的注解类FilterFilters仅仅是Filter注解的数组,但Java编译器并不想让程序员意识到Filters的存在。这样,接口Filterable就拥有了两次Filter(并没有提到Filter)注解。

同时,反射相关的API提供了新的函数getAnnotationsByType()来返回重复注解的类型(请注意Filterable.class.getAnnotation( Filters.class )经编译器处理后将会返回Filters的实例)。

程序输出结果如下:


filter1 

filter2




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值