Java 注解

    Java在JDK5之后引入了"注解"的概念,实际上就是为了起到简化代码、易于理解的作用,并且通过注解也可以在编译时期发现一些代码格式的错误,更方便的进行开发。

注:这里只是简单记录下 Java 注解的相关概念,未详细讨论。且不涉及 Java 8 新加入的注解。后续会更新补充…

注解的声明类似于 接口 的声明,但稍有不同

// 声明注解使用 @interface 关键字
public @interface Test {
	String name() default "";
}
一、元注解

元注解就是标记其他注解的注解

  • @Target 约束注解应用的范围,取值范围为 ElementType 的枚举。(未指定 Target 值时,默认可用于以下任何类型)
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    /** 用于类、接口、枚举声明 */
    TYPE,

    /** Field declaration (includes enum constants) */
    /** 用于属性声明(包括枚举实例) */
    FIELD,

    /** Method declaration */
    /** 用于方法声明 */
    METHOD,

    /** Formal parameter declaration */
    /** 用于参数声明 */
    PARAMETER,

    /** Constructor declaration */
    /** 用于构造器声明 */
    CONSTRUCTOR,

    /** Local variable declaration */
    /** 用于局部变量声明 */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    /** 用于注解声明(声明在另一注解上) */
    ANNOTATION_TYPE,

    /** Package declaration */
    /** 用于包的声明 */
    PACKAGE,

    /**
     * Type parameter declaration
     * 用于类型参数声明
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     * 类型使用声明
     * @since 1.8
     */
    TYPE_USE
} 
  • @Retention 约束注解的生命周期,取值范围为 RetentionPolicy 的枚举
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文件中有效,运行时无效(默认类型)
     */
    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
}
  • @Documented 将被修饰的注解生成到 javadoc 中
    标记后使用 javadoc xxx.java 命令生成 javadoc 文件
  • @Inherited 让子类对象通过反射获取父类被 @Inherited 修饰的注解
二、Java内置注解
  • @Override 标明此方法覆盖了父类的方法
  • @Deprecated 标明已经过时的方法或类
  • @SuppressWarnningsz 关闭编译器警告(接受字段如下)

deprecation:使用了不赞成使用的类或方法时的警告;
unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型;
fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
path:在类路径、源文件路径等中有不存在的路径时的警告;
serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
finally:任何 finally 子句不能正常完成时的警告;
all:关于以上所有情况的警告。

三、注解可使用的数据类型
  • 8种基本数据类型(byte、short、int、long、float、double、char、boolean)
  • String
  • Class
  • enum
  • Annotation(注解本身)
  • 数组

    默认值:编译器对注解要求是 要么在注解声明是指定默认值,要么在使用注解时赋值。不能存在不确定的值。
    快捷方式:注解中自定义了 value的元素,当且仅当注解中只有一个需要赋值的元素时,可以直接赋值,不须使用“key=value”的形式。如:

@Retention(RetentionPolicy.RUNTIME)

也可使用

@Retention(value = RetentionPolicy.RUNTIME)

四、注解与反射

    当注解被定义了 @Retention(RetentionPolicy.RUNTIME) 时,我们可以在代码中通过反射获取注解信息,从而进行我们想要的操作。(因为只有在 RUNTIME 时注解在运行期是有效的)

相关方法:

方法名返回值说明
getAnnotation(Class<A> annotationClass)<A extends Annotation>该元素如果存在指定类型的注解,则返回该注解,否则返回 null。
getAnnotations()Annotation[]返回标注在此元素上的所有注解,包括父类注解
isAnnotationPresent(Class<? extends Annotation> annotationClass)boolean指定类型注解是否标注在此元素上
getDeclaredAnnotations()Annotation[]返回标注在此元素上的所有注解,不包括父类注解

下面实现一个使用注解的例子:
    书店里有很多种类型的书,为了方便查看,将书的相关信息存放在注解中,通过反射获取其内容

  1. 定义一个 Book 注解,将书的相关属性进行定义(由于注解要存在于运行时,这里设置 RetentionPolicy.RUNTIME)
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {
	/**
	 * 书名
	 */
	String name();
	
	/**
	 * 价格
	 */
	double price();
	
	/**
	 * 备注
	 */
	String remarks() default "";
} 
  1. 定义一个 书店 类,进行配置书籍的相关信息
public class BookShop {
	@Book(name="文学", price=30)
	private String literature;
	
	@Book(name="科幻", price=40, remarks="限时8折")
	private String scienceFiction;
	
	@Book(name="体育", price=22, remarks="新版上架")
	private String sports;
}
  1. 通过反射获取信息
public class Main {
	public static void main(String[] args) throws Exception {
		Class<?> cls = BookShop.class;
		// 获取属性元素
		Field[] fields = cls.getDeclaredFields();
		// 遍历属性元素,获取书籍注解的内容
		for (Field field : fields) {
			// 获取Book注解
			Annotation annotation = field.getAnnotation(Book.class);
			if (annotation != null && annotation instanceof Book) {
				Book book = (Book) annotation;
				// 取值
				StringBuilder builder = new StringBuilder();
				builder.append(book.name()).append("\t")
						.append(book.price()).append("\t")
						.append(book.remarks());
				System.out.println(builder.toString());
			}
		}
	}
}

输出结果:

文学 30.0
科幻 40.0 限时8折
体育 22.0 新版上架

注:在细分的话也可根据书籍类型划分多种类,每一个类下有多种图书,再声明一个书籍分类的注解即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值