Java - 注解(Annotation)(注解示例、JDK中的元注解)

注解概述

  1. JDK5.0开始,Java增加了对元数据(MetaData)的支持,也就是注解(Annotation)。
  2. 注解其实就是代码里的特殊标记,可以理解为标签,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用注解,程序员可以在不改变原有逻辑的情况下在原文件嵌入一些补充信息。代码分析工具,开发工具和部署工具可以通过这些补充信息进行验证或进行部署。
  3. 注解可以像修饰符一样被使用,可用于修饰构造器方法成员变量参数局部变量的声明,这些信息被保存在 Annotation 的 name-value 对中。
  4. 在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能、忽略警告等。在 JavaEE / Android 中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替 JavaEE 旧版中所遗留的繁冗代码和 XML 配置等。
  5. 未来的开发模式都是基于注解的,这JPA是基于注解的,Spring2.5 以上都是基于注解的,Hibernate3.x 以后也是基于注解的,现在Struts2 有一部分也是基于注解的。注解是一种趋势,一定程度上可以说 框架=注解+反射+设计模式

注解示例

    使用 Annotation 时要在前面增加 @ 符号,并把 Annotation 当成一个修饰符使用。用于修饰它支持的程序元素。
    示例一:生成文档相关的注解

@author:标明开发该类模块的作者,多个作者之间使用 “,” 隔开
@version:标明该类模块的版本
@see:参考转向,也就是相关主题
@since:从哪个版本开始增加的
@param:对方法中某个参数的说明,如果没有参数就不用写
@return:对方法返回值的说明,如果方法的返回值类型是void就不用写
@exception:对方法可能抛出的异常进行说明,如果方法没有用throws显式抛出的异常就不用写
其中:
        @param,@return,@exception这三个标记都是只用于方法的。
        @param的格式:@param 形参名 形参类型 形参说明
        @return的格式:@return 返回值类型 返回值说明
        @exception的格式:@exception 异常类型 异常说明
        @param和@exception可以并列多个

    示例二:在编译时进行格式检查JDK的内置的三个基本注解

@Override:重写父类方法,该注解只能用于方法
@Deprecated:用于表示所修饰的元素(类、方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择(仍然可以使用,但尽量不用)
@SuppressWarnings:抑制编译器警告

    示例三:跟踪代码依赖性,实现替代配置文件功能,极大提高了效率(多用于框架)

Servlet3.0 提供了 @WebServlet(),使得不再需要在web.xml文件中进行Servlet的部署

自定义注解

    定义新的Annotation类型用 @interface 关键字,自定义注解会自动继承java.lang.annotation.Annotation接口。
    需要注意的是,在注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组。
    注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。可以使用default给成员变量默认值。

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int id();
	String name() default "hello";
}

    上面代码定义 MyAnnotation 这个注解中拥有 id 和 name 两个属性。在使用的时候,我们应该给它们进行赋值。赋值的方式是在注解的括号内以 value=”” 形式,多个属性用 ,隔开。

@MyAnnotation(id = 3, name = "Tom")
public class Test {}

    或者使用默认值

@MyAnnotation(id = 3)
public class Test {}

    如果一个注解内仅仅只有一个名字为 value 的属性时,使用这个注解时可以直接将属性写到括号内。

public @interface Check {
    String value();
}

    下面两种使用方式是等价的

@Check("hi")
int a;

@Check(value="hi")
int a;

    还需要注意的一种情况是,一个注解没有任何属性,使用这个注解的时候,括号可以省略。

public @interface Perform {}

@Perform
public void testMethod(){}

JDK中的元注解

    JDK的元注解用于修饰其它注解,即注解的注解。JDK中有5个元注解:@Retention,@Target,@Documented,@Inherited,@Repeatable(JDK1.8加入)。

package java.lang.annotation;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

@Retention

    用于指定该 Annotation 的生命周期。@Retention包含一个RetentionPolicy类型的成员变量,使用@Retention必须为其value成员变量指定值,如:@Retention(RetentionPolicy.RUNTIME)

package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译时会被编译器丢弃。
RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行Java程序时,JVM不会保留注释。这是默认值
RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行Java程序时,JVM会保留注释。程序可以通过反射获取该注释。

@Target

    用于指定 Annotation 能用于修饰哪些程序元素。@Target也包含一个名为value的成员变量。

package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

ElementType.CONSTRUCTOR:用于描述构造器
ElementType.FIELD:用于描述
ElementType.LOCAL_VARIABLE:用于描述局部变量
ElementType.METHOD:用于描述方法
ElementType.PACKAGE:用于描述
ElementType.PARAMETER:用于描述参数
ElementType.TYPE:用于描述接口(包括注解类型)、enum声明

@Documented

    所修饰的注解在被 javadoc 解析时保留下来。默认情况下,javadoc 是不包括注解的。
    定义了 @Documented 的 Retention 值必须为 RUNTIME

@Inherited

    被它修饰的注解具有继承性,如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解。

@Repeatable

    被修饰的注解是可重复的,注解的值可以是多个。

@interface Persons {
    Person[] value();
}

@Repeatable(Persons.class)
@interface Person{
    String role default "";
}

@Person(role="artist")
@Person(role="coder") // 赋值
@Person(role="PM")
public class SuperMan{}

    注意上面的代码,@Repeatable 注解了 Person。而 @Repeatable 后面括号中的类相当于一个容器注解,用来存放其它注解。容器注解里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组

反射与注解

    注解通过反射获取。首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}

    通过 getAnnotation() 或者是 getAnnotations() 方法来获取 Annotation 对象。前一种方法返回指定类型的注解,后一种方法返回注解到这个元素上的所有注解。

public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}

public Annotation[] getAnnotations() {}
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

@MyAnnotation(id = 128, name = "HXP")
public class AnnotationTest {
		
	@Deprecated
	public static void func() {	}
	
	public static void main(String[] args) {		
		Class<?> clazz = AnnotationTest.class;
		boolean hasAnnotation = clazz.isAnnotationPresent(MyAnnotation.class);
		if (hasAnnotation) {
			MyAnnotation myAnnotation = clazz.getAnnotation(MyAnnotation.class);
			System.out.println("id: " + myAnnotation.id());
			System.out.println("name: " + myAnnotation.name());
		}
		try {
			Method method = clazz.getDeclaredMethod("func");
			Annotation[] annotations = method.getAnnotations();
			for (Annotation annotation : annotations) {
				System.out.println("method annotation: " + annotation.annotationType().getSimpleName());
			}
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
		
	}
}

秒懂,Java 注解 (Annotation)你可以这样学原地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值