JDK1.5出现的新特性。在java.lang.annotation包中。
对于过时的语句,java会提示过时了,通过@SuppressWarnings("Deprecation")在DOS中取消提示,但Eclipse无法取消。
这就是注解,相当于标记。编译器、开发工具、javac通过反射获得注解里的内容,进而明确应该做什么、不应该做什么。注解可以加在包、类、属性、方法、参数及局部变量之上。
一个注解就是一个类。@SuppressWarnings,取消警告。@Deprecated,已过时,老版可以用,新版无法用。
注解的应用
在源程序中,调用一个类,这个类会用到注解,需要先准备好注解类,类在调用注解类的对象。注解类的写法类似接口,@interface。先写好注解类A,将注解放在类B中,类C在调用类B时通过反射获得注解类A的内容,进而明确该做什么、不该做什么。可以加上多个注解,加上的实际是注解类的对象:@interfaceA。
main()方法必须放在一个类下,但与这个类不一定有所属关系。
在注解类A上加注解B,这个注解B只为这个注解类A服务,B称为“元注解”。类似的还有元信息、元数据。元注解有2个:Rentention和Target。对注解类的注解,可以理解为注解类的属性。
(1) Rentention注解类
注解的生命周期:Java源文件—》class文件—》内存中的字节码。编译或者运行时,都有可能会取消注解。Rentention的3种取值意味让注解保留到哪个阶段,RententionPolicy.SOURCE、RententionPolicy.CLASS(默认值)、RententionPolicy.RUNTIME。
@Override、@SuppressWarnings是默认保留到SOURCE阶段;
@Deprecated是保留到RUNTIME阶段。
Rentention的值是枚举RententionPolicy的值,只有3个:SOURCE、CLASS、RUNTIME。
(2)Target注解类
性质和Rentention一样,都是注解类的属性,表示注解类应该在什么位置,对那一块的数据有效。例如,@Target(ElementType.METHOD)
类、接口、枚举、注解这一类事物用TYPE表示,Class的父类,JDK1.5的新特性。
注解的基本属性
属性,给注解提供更加详细的信息。
注解相当于接口,属性相当于方法。例如,@ItcastAnnotation(color="red"),给属性赋值,取值时类似调用方法,例如,System.out.println(annotation.color());。
所有的属性必须全部出现,除非有缺省值。
如果只有value属性,没有其他属性,可以不写=,只针对value,例如,@SuppressWarnings("Deprecation")。或者有其他属性而且有缺省值,
例如,String color() default "blue";,此时value单独出现,不用=。
获得注解的属性的值,例如
if(AnnotationDemo.class.isAnnotationPresent(ItmAnnotation.class)){
ItmAnnotation annotation =
(ItmAnnotation)AnnotationDemo.class.getAnnotation(ItmAnnotation.class);
System.out.println(annotation.color());
}
}
利用反射获得注解的对象,在让该对象调用属性对应的方法。注意类型转换。
Rentention和Target也是属性,都是value对应的值,值的类型分别是RententionPolicy和ElementType,例如,@Retention(value=RetentionPolicy.RUNTIME)。
注解的高级属性
给注解增加高级属性,数组、枚举、注解。
例如,int[] arr() default {3,7,5};,MyAnnotation(arr={3,7,6})。如果数组只有1个元素,可以不加{}。
@Target({ElementType.METHOD,ElementType.TYPE})也是数组类型的属性。
枚举类型的属性
EnumerationDemo.TrafficLamp lamp() default EnumerationDemo.TrafficLamp.RED;
//调用注解的类上
@ItcastAnnotation(lamp=EnumerationDemo.TrafficLamp.YELLOW)
//对注解进行操作
System.out.println(annotation.lamp().nextLamp().name());
将一个注解类作为属性加入到另一个注解类中。
MetaAnnotation annotationAtt() default @MetaAnnotation("Jobs")
@ItcastAnnotation(annotationAtt=@MetaAnnotation("Kim"))
annotation.annotationAtt().value()
注解的返回值可以是8个基本类型、String、Class、枚举以及前面类型的数组,内部还有属性。
需要详细学习注解,可以通过java语言规范,即languagespecification。
- <span style="font-size:18px;">import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- import com.java.testDay.EnumTest;
- //下面這個注解 視為 這個 ItmAnnotation 注解 服務的。
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD,ElementType.TYPE})
- public @interface ItmAnnotation {
- String color() default "blue";
- String value();
- int[] arrayAttr() default{3,4,4};
- // 枚举 的 注解。EnumTest.TrafficLamp.RED----这是枚举的实例对象。
- EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
- MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");
- }
- </span>
- <span style="font-size:18px;">package com.java.testDay;
- import java.util.Date;
- public class EnumTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- WeekDay1 weekDay = WeekDay1.MON;
- System.out.println(weekDay.nextDay());
- WeekDay weekDay2 = WeekDay.FRI;
- System.out.println(weekDay2);
- System.out.println(weekDay2.name());
- System.out.println(weekDay2.ordinal());
- System.out.println(WeekDay.valueOf("SUN").toString());
- System.out.println(WeekDay.values().length);
- new Date(300){};
- }
- public enum WeekDay{
- SUN(1),MON(),TUE,WED,THI,FRI,SAT;
- private WeekDay(){System.out.println("first");}
- private WeekDay(int day){System.out.println("second");}
- }
- public enum TrafficLamp{
- RED(30){
- public TrafficLamp nextLamp(){
- return GREEN;
- }
- },
- GREEN(45){
- public TrafficLamp nextLamp(){
- return YELLOW;
- }
- },
- YELLOW(5){
- public TrafficLamp nextLamp(){
- return RED;
- }
- };
- public abstract TrafficLamp nextLamp();
- private int time;
- private TrafficLamp(int time){this.time = time;}
- }
- }
- </span>
- <span style="font-size:18px;">package com.java.test;
- public @interface MetaAnnotation {
- String value();
- }
- </span>
- <span style="font-size:18px;">package com.java.test;
- // 注解 就相當於 一個牌子。
- @ItmAnnotation(annotationAttr=@MetaAnnotation("hhh"),color="red",value="abc",arrayAttr={1,2,3})// 我只写 color会报错,是不是 类似接口啊,
- // annotationAttr=@MetaAnnotation("hhh") 注解的属性值 又是一个注解。。。。
- // 若数组只有一个值:可以写成这样:arrayAttr=1
- // 如果只有 一个 value属性需要你设值,就不写 “value=” 了。也就是 直接写值就可以了,如果不这样的话,也可以把别的属性 设置为 默认的。
- public class AnnotationTest {
- /**
- * @param args
- */
- @SuppressWarnings("deprecation")
- @ItmAnnotation("xyz") // 必须把其他的属性 改为 默认的。。
- public static void main(String[] args) throws Exception{
- System.runFinalizersOnExit(true);
- // 檢查 ItmAnnotation.class 在不在。
- // 这里主要 应用了 反射的知识,来检查以及得到 要操作的类。也就是 你自己要用的 东西,你想要用什么 就去拿什么。
- if (AnnotationTest.class.isAnnotationPresent(ItmAnnotation.class)) {
- // 如果在的話 就得到 這個注解。
- ItmAnnotation annotation =AnnotationTest.class.getAnnotation(ItmAnnotation.class);
- System.out.println("得到,ItmAnnotation :" + annotation);
- System.out.println("\n");
- // 这时,你就可以用到 ItmAnnotation 里面的 color属性了。再用之前 必须在类名上 加上标示。
- // 也就是说:你想要用什么,可以让你用,但是 你必须 要告诉一声,要立个牌坊,哈哈。
- 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());
- }
- }
- @Deprecated
- public static void sayHello(){
- System.out.println("hi,哈哈哈");
- }
- }
- </span>
还有一个 不错的例子: