我们知道注解是在JDK1.5引入的,可能有的人没有用过注解,所以感觉注解这个东西没有什么用,但是深入了解注解,对以后学习框架有所帮助的,后面提到的JavaWeb的框架中很多都是基于注解的技术,

其实注解你可以把他认为是一种标记,和接口差不多,我们知道有些接口只起到标记作用(通常叫做标记接口如:Serializable,Cloneable等,就是接口中没有任何东西,只做为一种标记),下面来看一下注解的定义和使用的方法:

定义一个注解和接口差不多:使用关键字@interface

代码如下:

package com.annotation.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
//javac将源程序编译成class文件,在这个过程中类上的注解是否保留到class文件中
//注解的生命周期的三个阶段:源程序,class文件,字节码
//默认值是在class阶段
//Override SuppressWarning Deprecated:按照编译器的标准来判断这三个阶段
@Target({ElementType.ANNOTATION_TYPE,ElementType.TYPE,ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.LOCAL_VARIABLE,ElementType.METHOD,ElementType.PACKAGE,ElementType.PARAMETER})
//注解添加的目标
public @interface MyAnnotation{ String color() default "red";//属性String
int[] value() default {1};//属性int[],这是个特殊的属性,如果只有一个value属性需要去设置值,可以不需要设置"value="
MyEnum enums() default MyEnum.ONE;//属性enum,返回值是MyEnum枚举
MetaAnnotation annotation() default @MetaAnnotation("red");//注解属性
//静态常量
boolean isRunning = false; }

这个注解上面我们又添加了Java中已经定义的注解:@Retention和@Target,下面来讲解一下这两个注解的作用

首先来看一下@Retention注解的作用:他的作用是标记该注解的生命周期(即三个阶段:java源程序,class文件,字节码),看一下他的源代码:

/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ package java.lang.annotation; /**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}

@Retention注解中只有一个value属性,这个属性的类型是一个枚举类型,有三个值SOURCE,CLASS,RUNTIME

/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ package java.lang.annotation; /**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE, /**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS, /**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}

从注释中可以看出,

SOURCE:是将注解保存在源程序中,但是会被编译器遗弃的,就是不会保留到class文件中了,而且这个是默认值

CLASS:是将注解会被编译器保存到class文件中,但是不会保留到VM运行的时候,就是会被在JVM加载字节码的时候遗弃

RUNTIME:是将注解保存到运行的时候,这时候也就可以使用反射技术获取到这个注解的实例对象了

下面来看一下例子:

在定义一个注解,这个注解是被定义在MyAnnotation注解中的,我们叫这样的注解是原注解:

package com.annotation.demo;

public @interface MetaAnnotation {

	String name() default "red";
String value(); }

还有我们自定义了枚举:

package com.annotation.demo;

public enum MyEnum {
ONE,TWO,THREE;
}

在来看一下,使用了MyAnnotation注解的类:

package com.annotation.demo;

@MyAnnotation(color="red",value={1,2,3},enums=MyEnum.ONE)
public class UseAnnotation { public void fun(){
} }

这个注解的具体使用,后面再说,我们现在先来看一下上面提到的@Retention注解的作用,最后来看一下获取到UseAnnotation类上的注解:

package com.annotation.demo;

public class AnnotationTest {

	public static void main(String[] args){
//UserAnnotation类中使用到了MyAnnotation自定的注解
UseAnnotation.class.isAnnotationPresent(MyAnnotation.class);
//获取UserAnnotation中上的注解
MyAnnotation annotation = (MyAnnotation) UseAnnotation.class.getAnnotation(MyAnnotation.class);
//打印注解
System.out.println(annotation);
System.out.println(annotation.color());
System.out.println(annotation.enums());
System.out.println(annotation.value().length);
} }

运行结果:

打印出来了注解

下面我们将MyAnnotation注解中的@Retention(RetentionPolicy.RUNTIME)注解改成@Retention(RetentionPolicy.SOURCE),这时候在运行:

发现运行打印的枚举结果是null,如果将@Retention(RetentionPolicy.CLASS)效果也是一样的,这个就是和我们上面所说的那样,这个注解没有保存到运行的时候,我们是无从类中获取到注解的实例对象的,这样@Retention注解类型的作用就清楚了,刚开始搞这个东西的时候,总是打印出来的是null,而@Retention的默认值是SOURCE,找了很多资料,才搞定的,很纠结呀!

下面在来看一下@Target注解:

源代码如下:

/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ package java.lang.annotation; /**
* Indicates the kinds of program element to which an annotation type
* is applicable. If a Target meta-annotation is not present on an
* annotation type declaration, the declared type may be used on any
* program element. If such a meta-annotation is present, the compiler
* will enforce the specified usage restriction.
*
* For example, this meta-annotation indicates that the declared type is
* itself a meta-annotation type. It can only be used on annotation type
* declarations:
* <pre>
* @Target(ElementType.ANNOTATION_TYPE)
* public @interface MetaAnnotationType {
* ...
* }
* </pre>
* This meta-annotation indicates that the declared type is intended solely
* for use as a member type in complex annotation type declarations. It
* cannot be used to annotate anything directly:
* <pre>
* @Target({})
* public @interface MemberType {
* ...
* }
* </pre>
* It is a compile-time error for a single ElementType constant to
* appear more than once in a Target annotation. For example, the
* following meta-annotation is illegal:
* <pre>
* @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
* public @interface Bogus {
* ...
* }
* </pre>
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}

他里面也只有一个属性value,是个ElementType类型的数组:

看一下ElementType源代码:

/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ package java.lang.annotation; /**
* A program element type. The constants of this enumerated type
* provide a simple classification of the declared elements in a
* Java program.
*
* <p>These constants are used with the {@link Target} meta-annotation type
* to specify where it is legal to use an annotation type.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE, /** Field declaration (includes enum constants) */
FIELD, /** Method declaration */
METHOD, /** Parameter declaration */
PARAMETER, /** Constructor declaration */
CONSTRUCTOR, /** Local variable declaration */
LOCAL_VARIABLE, /** Annotation type declaration */
ANNOTATION_TYPE, /** Package declaration */
PACKAGE
}

这里可以看到总共有TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,ANNOTATION_TYPE,PACKAGE这七个值分别表示的是添加注解的对象类型:

TYPE:是Java1.5引入的新类型,他概括了所有的类型,不止是Class类,还有枚举Enum等,所以这里没有用CLASS类型了

FIELD:是类中的字段

METHOD:是类中的方法

PARAMETER:是方法中的形参(传递的参数类型)

CONSTRUCTOR:是构造方法

LOCAL_VARIABLE:方法中定义的变量

ANNOTATION_TYPE:注解可以添加在注解中

PACKAGE:注解添加在包中

这部分比较简单,这里就不掩饰了,我们一般是把这7个值都设置进去(如果没有特殊要求的话)

下面来看一下注解中的定义和使用方法:

public @interface MyAnnotation{

	String color() default "red";//属性String
int[] value() default {1};//属性int[],这是个特殊的属性,如果只有一个value属性需要去设置值,可以不需要设置"value="
MyEnum enums() default MyEnum.ONE;//属性enum,返回值是MyEnum枚举
MetaAnnotation annotation() default @MetaAnnotation("red");//注解属性
//静态常量
boolean isRunning = false; }

注解中定义的属性和接口中定义的是有区别的,注解中定义一个属性:Void fun() default ===>返回类型 属性名称 默认值,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。当然注解中定义的类型有:注解参数的可支持数据类型:

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)

2.String类型

3.Class类型

4.enum类型

5.Annotation类型

6.以上所有类型的数组

当然注解中也可以定义一个字段,这个字段的类型和接口中的类型是一样的,默认的是静态常量,下面来看一下注解的使用方法:

package com.annotation.demo;

@MyAnnotation(color="red",value={1,2,3},enums=MyEnum.ONE)
public class UseAnnotation { public void fun(){
} }

给属性赋值也是很简单的,直接使用“=”即可,这里要注意的是注解中有个特殊的属性,那就是value属性,我们先来看一下@Retention注解的源代码

public @interface Retention {
RetentionPolicy value();
}

再看一下他的使用方法:

@Retention(RetentionPolicy.SOURCE)

我们发现这个使用没有用到“=”按照常理应该是:value=RetentionPolicy.SOURCE这样使用的,所以这里value就是个特殊的属性了,名称不能写错了,是value,当一个注解中有且只有一个属性value的时候,我们可以省略"=",直接这样赋值,这里要注意是有且仅有一个,如果注解中有多个属性,这时候就不能这样操作了,像我们自定义的注解MyAnnotation中还有其他的注解,所以就不能省略"="了,当然如果你在其他的属性中在定义一个默认值就是default,这时候也还是可以省略“=”的,其他的情况就不行了

写到这里就算结束了,这个注解是很简单的,他的作用也很明白,就是标记的作用,我们需要自己顶一个注解管理器(spring中就是这样做的,这样就可以查到这个类上的所有标记了,通过这个标记在对这个类进行相应的操作)

Java高新技术第三篇:注解的使用的更多相关文章

  1. 黑马程序员——【Java高新技术】——JavaBean、注解

    ---------- android培训.java培训.期待与您交流! ---------- 一.JavaBean * 通过内省引入JavaBean:内省对应的英文全程是IntroSpector.在J ...

  2. 从.Net到Java学习第三篇——spring boot+mybatis+mysql

    从.Net到Java学习第一篇——开篇 环境:mysql5.7 新建mysql数据库demo,然后执行如下sql脚本进行数据表创建和数据初始化: -- ------------------------ ...

  3. Java系列--第三篇 基于Maven的Android开发CAIO

    学习要打好基础,这里用一个项目来学习一下Android的组件,参考网址为这个但不限于这个.有些东西的学习,理解三遍理论还不如一遍操作,所谓理论来自实践,实践是检验真理的唯一标准.所以,虽然看懂了那篇文 ...

  4. Java学习第三篇:类的三大特征,抽象类,接口,final关键字

    一.类的三大特征 1.封装性 (1).什么是封装 封装就是把抽象出的数据和对数据的操作封装在一起, 数据被保护在内部, 程序的其他部分只有通过被授权的操作(成员方法), 才能对数据进行操作. (2). ...

  5. 学习java随笔第三篇:java的基本数据类型

    数据类型 一:整型 1.十进制 2.八进制 八进制数是满8进1,包含0~7的8个数字,在整数前面添加一个"0",表示是八进制数. 3.十六进制 十六进制数是满16进1,包含0~9, ...

  6. Java【第三篇】基本语法之--选择结构

    Java分支语句分类 分支语句根据一定的条件有选择地执行或跳过特定的语句,分为两类: if-else 语句 switch 语句 if-else语句语法格式 if(布尔表达式){ 语句或语句块; } i ...

  7. 聊聊、Java 命令 第三篇

    这篇随笔主要写启动 jar 时,如果需要依赖其他的 jar 包该怎么处理,我会以 rabbitMQ 客服端启动为例. package com.rockcode.www.rabbitmq; import ...

  8. java核心技术第三篇之JDBC第一篇

    01.JDBC_两个重要的概念: 1).什么是数据库驱动程序:由数据库厂商提供,面向某种特定的编程语言所开发的一套访问本数据库的类库. 驱动包一般由两种语言组成,前端是:面向某种特定编程语言的语言:后 ...

  9. 【JAVA并发第三篇】线程间通信

    线程间的通信 JVM在运行时会将自己管理的内存区域,划分为不同的数据区,称为运行时数据区.每个线程都有自己私有的内存空间,如下图示: Java线程按照自己虚拟机栈中的方法代码一步一步的执行下去,在这一 ...

随机推荐

  1. 使用Gradle发布项目到JCenter仓库 (转载)

    原文:使用Gradle发布项目到JCenter仓库 这篇文章介绍通过Gradle把开源项目发布到公共仓库JCenter中,方便你我他的事情,我们都是很懒的嘛.JCenter现在是Android Stu ...

  2. scrollHeight与offsetHeight

    offsetXxx 是 HTMLElement 的属性, HTMLElement 接口表示所有的 HTML 元素,scrollXxx 是 Element 的属性,Element 是一个通用性非常强的基 ...

  3. promise、async、await、settimeout异步原理与执行顺序

    一道经典的前端笔试题,你能一眼写出他们的执行结果吗? async function async1() { console.log("async1 start"); await as ...

  4. Android中的隐藏API和Internal包的使用之获取应用电量排行

    今天老大安排一个任务叫我获取手机中应用耗电排行(时间是前天晚上7点到第二天早上10点),所以在网上各种搜索,没想到这种资料还是很多的,发现了一个主要的类:PowerProfile,但是可以的是,这个类 ...

  5. ES6 教程

    上次分享了es6开发环境的搭建,本次接着分享es6常用的特性. es6常用的语法参考   :    https://blog.csdn.net/itzhongzi/article/details/73 ...

  6. Mysql 导入日文数据乱码问题

    做数据迁移后,通过ui发现有日文数据是乱码,通过ui直接修改日文则显示正常. 查了下资料,mysql字符集的作用如下: MySQL字符集设置 • 系统变量:– character_set_server ...

  7. PAT_A1103#Integer Factorization

    Source: PAT A1103 Integer Factorization (30 分) Description: The K−P factorization of a positive inte ...

  8. PHP-FPM 远程代码执行漏洞(CVE-2019-11043)复现-含EXP

    搭建容器 安装golang 利用程序 https://github.com/neex/phuip-fpizdam 安装git Cobra包安装 go get -v github.com/spf13/c ...

  9. 深入浅出JS:Two

    JS中的Promise: MDN上面对promise的描述:Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值. 可以直接对字面上理解:Promise:承诺,一诺千金,只 ...

  10. 【POJ】1679 The Unique MST

    题目链接:http://poj.org/problem?id=1679 题意:给你一组数据,让你判断是否是唯一的最小生成树. 题解:这里用的是kuangbin大佬的次小生成树的模板.直接判断一下次小生 ...