java注解之基础篇


(本来要读一下PendingIntent的源码,发现好多注解,所以就脑补了下注解)

一.什么是注解?

  在JDK1.5后java开始了对元数据(Metadata)的支持,也就是注解(Annotation)。
 关于Metadata的介绍:
    Metadata is "data that provides information about other data".Two types of metadata exist: structural metadata and descriptive metadata. Structural metadata is data about the containers of data. Descriptive metadata uses individual instances of application data or the data content[1].
       摘自 网址  https://en.wikipedia.org/wiki/Metadata
    大致意思是说:

    元数据是一种用来为其它数据提供数据的数据。元数据有两种形式:结构元数据和描述性元数据。其实,在java中所谓元数据(注解)就是包含了接口、类、方法和变量的一些信息,或者元数据是对接口、类、方法、变量等等作得的标记。这些标记在将来可以在编译、类加载、运行时读取出来,根据标记的不同,对它所标记的数据进行特别的处理。

二.既然它是一种标记,那么它可以用来标记哪些数据呢?
 
     包、接口、类、构造方法、方法、字段、参数、局部变量。

三.注解和注释
 注释:1)它是对一些代码的描述,主要目的是为了提高代码的可读性,为自己和其他程序员阅读代码提供便利。
           2)注释不能被编译,更不能加载和执行。
  
 注解:1)它虽然是一种其它代码的标记,但是它自身也是一段程序代码,能够被编译,能够被jvm解释执行。
   相同点:他们的改变并不影响其他代码的执行,无论是增加还是删除,其他被他们修饰的代码都能顺利运行(这句      话并不严谨)

四.jdk中提供的注解:
      
   1)@Override
         它的作用是用来指定方法覆载的,它强制一个子类必须覆盖父类的方法。当一个子类的方法被@Override修饰时,编译时,编译器就会到其父类中寻找这个方法,如果没有找到就会后编译错误。
   2)@Deprecated
         当一个类或者方法被@Deprecated修饰后,就意味这它已经过时了,不再推荐使用。如果继续使用就出编译器就会发出警告。
   3)@Suppress Warnings
          它的作用是抑制编译器的警告。比如上面如果出现方法过期的编译时警告,如果我们想要将警告取消,我们就可以使用@SuppressWarnings("deprecation")对相应的方法进行修饰。
   4)@Safe Varargs (JDK 1.7) 抑制对污染警告
   5)@FunctionalInterface(JDK 1.8)
        用来告诉编译器,该接口只能包括一个抽象方法。(该注解只能用于修饰接口)

五.元注解(Meta Annotation)
 
       顾名思义,元注解就是用来修饰注解的注解,用于注解的定义。

1.四个的元注解:
      
        1)@Retention
            作用:用来规定被它修饰的注解的生命范围
                ** RetentionPolicy.RUNTIME  
                       编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
                ** RetentionPolicy.CLASS
                       编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。这是默认的行为。
                ** RetentionPolicy.SOURCE 
                       编译器要丢弃的注释。

         源码:

                       @Documented
			@Retention(RetentionPolicy.RUNTIME)
			@Target(ElementType.ANNOTATION_TYPE)
			public @interface Retention {
                            RetentionPolicy value();
                        }
          注:1.JDK提供的五种基本注解的生命期为RetentionPolicy.CLASS
                 2.RetentionPolicy是一个枚举。
                 3.@Retention只能用于修饰注解的定义,用于修饰注解可以保留多长时间。
4.由源码可看出,@Retention只能接收一个参数。


 2)@Target
 
           作用:用来规定被它修饰的注解所能修饰的程序元素
               **  ElementType.ANNOTATION_TYPE
                         被它修饰的注解只能用于修饰注解定义


               **  ElementType.CONSTRUCTOR 
                         被它修饰的注解只能用于修饰构造方法定义 


               **  ElementType.FIELD
                         被它修饰的注解只能用于修饰字段定义


               **  ElementType.LOCAL_VARIABLE 
                         被它修饰的注解只能用于修饰局部变量定义


               **  ElementType.METHOD 
                         被它修饰的注解只能用于修饰方法定义


               **  ElementType.PACKAGE 
                         被它修饰的注解只能用于修饰包定义


               **  ElementType.PARAMETER 
                         被它修饰的注解只能用于修饰参数定义


               **  ElementType.TYPE 
                         被它修饰的注解只能用于修饰类、接口、枚举定义

 

         源码:

                 @Documented
		 @Retention(RetentionPolicy.RUNTIME)
		 @Target(ElementType.ANNOTATION_TYPE)
		 public @interface Target {
   
    			ElementType[] value();
		 }
         注:由源码可看出,@Target可接收多个参数。


    3)@Documented
           作用:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。如果一个程序元素被一个被@Documented所修饰的注解修饰,那么该程序元素的API文档中将会包括该注解的说明。 

           源码:

                  @Documented
                  @Retention(RetentionPolicy.RUNTIME)
		  @Target(ElementType.ANNOTATION_TYPE)
		  public @interface Documented {
		}
            注: @Documented是一个标记注解,没有成员。


 4)@Inherited 
           作用:@Inherited 是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

            源码

            <span style="font-size:18px;">      @Documented
               @Retention(RetentionPolicy.RUNTIME)
               @Target(ElementType.ANNOTATION_TYPE)
               public @interface Inherited {
              }</span>
                注: @Inherited 是一个标记注解,没有成员


六、自定义注解
     1、格式
           public @interface 注解名 {定义体}
          说明:

              1)就像定义类用class关键字,定义注解用@interface关键字。
               2)权限修饰符和类名的原则与类或接口相同。
               3)定义体:如下。

 
      2.关于定义体的说明:
           1)定义体中主要作用是规定将来的自定义注解的参数类型及名称,定义体可以是空的。
           2)注解的参数类型主要包括:
                  *基本数据类型(byte、short、int、long、float、double、char和boolean)
                  *String类型
                  *Class类型
                  *enum类型
                  *Annotation类型
                  *以上类型的数组
           3)参数的权限修饰符只能用public或者默认。
           4)如果定义体中只有一个参数,最好把它命名为value,如String value()。
           5)如4中的String value(),括号里不能有参数,并且后面不能抛异常。


       3 自定义注解举例:

1)           

             @Target(ElementType.METHOD)
              public @interface Test1{
                 
                  }
              说明:定义了一个注解Test1,它的修饰对象是方法,并且没有参数。

              2)

              @Retention(RetentionPolicy.RUNTIME)
              @Target(ElementType.FIELD)
              public @interface Test2{
                    int id() default -1;
                    String name();
                  }
              说明: 定义了一个注解Test2,它的修饰对象是字段,有两个参数:id (默认值为-1)、name。

         **第一种没有参数的的Annotation我们称它们为标记注解。标记注解仅仅通过自身存在与否来提供信息(类似于标记接口)。      
         **第二种带有参数的Annotation我们称它们为元数据注解。

 

七、注解的解析
   
   描述:通过反射来获取类、方法或成员上的运行时注解,从而动态控制程序运行的逻辑。
   

      自定义注解Test代码:

                package test5;

		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.TYPE)
		public @interface Test {
			String value();
		}
    
        Student代码:
                package test5;

		@Test("this is a student.")
		public class Student {
    
		}

        测试类:

		package test5;

     		public class AnnitationDemo {

			public static void main(String[] args) {
				Class<?> s = null;
				Test t = null;
			// 第一步,使用类加载器加载Student类
			try {
			s = Class.forName("test5.Student");
			} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			}

			// 第二步,判断Student上是否有叫做“Test”的注解,如果有取出来
			if (s != null && s.isAnnotationPresent(Test.class)) {

			t = s.getAnnotation(Test.class);

			}
			// 第三步,控制台打印注解
			System.out.println("注解——" + t.value());
		}

	}
     

         结果:

                 

                  

            

八、本文参考

                1 > 李刚 《疯狂java讲义》 (第三版)

                2 >竹子 《深入理解Java:注解(Annotation)自定义注解入门》 

                     http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

          


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值