注解

注意,本章只是简单介绍注解

注解的使用主要在框架和反射中体现,到后期在深入学习

1、常见的Annotation示例

示例一: 生成文档相关的注解

在生成文档的时候,会弹出部分注解,如@author:表明开发作者;@return:对方法返回值的说明;@date:开发创作日期

示例二: JDK三个基本注解

@Override:该注解只能用于方法,判断是否重写父类方法

@Deprecated:用于表达该元素已过时,比如 new Date(int year,int month,nit day) 方法已过时

@SuppressWarning:抑制编译器警告。当已经初始化的结构未得到使用时,可以用这个注解,来让系统不再警告提示

示例三: 跟踪代码依赖性,实现替代配置文件功能

Servlet3.0 提供了注解,使得不需要在 web.xml 文件中进行 Servlet 的部署

2、JDK内置三个基本注解

2.1、@Override

class Person{
	public void show(){
		System.out.println("父类方法");
	}
}
class Student extends Person{
	@Override
	public void show(){
		System.out.println("子类方法");
	}
}

在标注了该注解的地方,就必须是重写了方法,否则会提示报错

如下

public class Untitled {
	public static void main(String[] args) {
		Person p = new Student();
		p.show();      //父类方法
	}
}
class Person{
	public void show(){
		System.out.println("父类方法");
	}
}
class Student extends Person{
	@Override     //此处会报错,有红线
	public void show111(){
		System.out.println("子类方法");
	}
	
	//这里就是正常的定义另外的一个方法
	public void show222(){
		System.out.println("子类方法");
	}
}

2.2、@Deprecated

Date中的过时方法

public class Untitled {
	public static void main(String[] args) {
		Date d = new Date(2021,,10,11);
		System.out.println(d);
	}
}

2.3、@SuppressWarning

在 IDEA 中,下面的num在未被使用的情况下,是灰色的

是一种提示

public class Untitled {
	public static void main(String[] args) {
		int num = 10;
	}
}

使用了 @SuppressWarning注解之后,就不会再有这种提示

public class Untitled {
	public static void main(String[] args) {
		@SuppressWarning("unused")
		int num = 10;
	}
}

3、自定义注解

查看JDK内置的基本注解 @SuppressWarning来模仿

@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention({RetentionPolicy.SOURCE})
public @interface SuppressWarning{
	String[] value();
}

步骤:
1、注解声明为@interface
2、内部定义成员,通常使用value表示
3、可以指定成员的默认值,使用default定义
4、如果注解没有成员,表示是一个标识作用,如@Override@Serializable

@Override没有成员,起标识作用

@Target(ElementType.METHOD)
@Retention({RetentionPolicy.SOURCE})
public @interface Override{
}

注意:
1、如果注解有成员,需要指定成员的值
2、自定义注解必须配上注解的信息处理流程(使用反射)才有意义
3、自定义注解继承了java.lang.Annotation接口

@interface关键字是和class、interface、enum并列的存在

内部定义成员,通常使用value表示,需要指定成员的值。如下:

//1、注解声明为`@interface`
public @interface MyAnnotation{
	//2、内部定义成员,通常使用`value`表示
	String value();   
}
@MyAnnotation(value = "草莓")   //此处必须有值,否则报错
class Test{
}

内部定义成员,可以指定成员的默认值,使用default定义。如下:

public @interface MyAnnotation{
	String value() default "小草莓";   
}
@MyAnnotation(value = "大西瓜")   //此处可以修改
class Test{
	@MyAnnotation()              //可以不填
	public void show(){}
}

4、JDK中四个元注解

元注解:指的就是给注解做注解的注解

元数据:String name = "草莓";,其中,String、name就是元数据

Retention:指定 Annotation 的生命周期。只有声明为RUNTIME的注解,才可以通过反射获取

Target:用于指定该注解能用于修饰哪些元素

Document:用于指定该注解将被 javadoc 提取成文档的时候,将注解保留在文档中

Inherited:指明该注解具有继承性,父类有该注解,子类自动继承该注解

4.1、@Retention

用于指定该注解的生命周期,其中包含了一个RetentionPolicy(是一个枚举类)的成员变量,使用@Retention的时候,必须为该 value 成员变量指定值:

1、RetentionPolicy.SOURCE:源码注解,在源文件中有效(源文件保留)
注解只在源码中存在,编译成.class文件就不存在了

2、RetentionPolicy.CLASS:编译时注解,在.class文件中有效(.class文件保留)——这是默认值
注解在源码和.class文件中都会存在。比如说@Override

3、RetentionPolicy.RUNTIME:运行时注解,在运行时有效(运行时保留)
在运行阶段还会起作用,甚至会影响运行逻辑的注解,程序可以通过反射获取该注解。比如说@Autowired

下图是类加载的过程,更好的理解三种注解(图片来源
在这里插入图片描述
@Override 的源码如下

@Target(ElementType.METHOD)
@Retention({RetentionPolicy.SOURCE})
public @interface Override{
}

4.2、@Target

用于指定该注解能用于修饰哪些元素,其中包含了一个ElementType(是一个枚举类)的成员变量,使用@Target的时候,必须为该 value 成员变量指定值:

CONSTRUCTOR构造器
FIELD
LOCAL_VARIABLE局部变量
METHOD方法
PACKAGE
PARAMETER参数
TYPE类、接口、注解、enum
@Target({FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
public @interface MyAnnotation{
	String value();   
}
@MyAnnotation(value = "大西瓜")       //会报错,因为@Target没有TYPE
class Test{
	@MyAnnotation(value = "小草莓")   //不会报错
	public void show(){}
}

4.3、@Document

用于指定该注解将被 javadoc 提取成文档的时候,将注解保留在文档中。(一般默认不保留)

比如: API 就是这样的一种文档

注意:
定义为 @Document 的注解的生命周期必须是 RetentionPolicy.RUNTIME

@Deprecated的源码如下

@Document
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface Deprecated{
}

4.4、@Inherited

指明该注解具有继承性,父类有该注解,子类自动继承该注解

public class Untitled {
	public static void main(String[] args) {
		//通过反射获取 Student 类的注解信息
		Class cc = Student.class;
		Annotation[] aa = cc.getAnnotation();
		for(int i = 0;i < aa.length; i ++){
			System.out.println(aa[i]);  //输出了MyAnnotation,说明有继承性
		}
	}
}
@MyAnnotation
class Person{}

class Student extends Person{}
@Inherited
public @interface MyAnnotation{
	String value();   
}

5、JDK8新特性:重复注解

①在MyAnnotation上声明@Repeatable,成员值为MyAnnos.class

MyAnnotation的 生命周期@Retention、适用范围@Target 和MyAnnos相同

//附上元注解@Repeatable,为其成员传入 自定义大注解
@Repeatable(MyAnnos.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface MyAnnotation{
	String value() default "hi";   
}

//定义一个成员为 自定义注解数组的 自定义大注解
//两个注解的 生命周期@Retention、适用范围@Target 需要保持一致
@Retention(RetentionPolicy.RUNTIME)
@Target({CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface MyAnnos{
	MyAnnotation[] value();   
}

对于 JDK 8 及以后

完成以上操作后,就可以进行以下形式的重复注解了

@MyAnnotation(value = "小草莓")
@MyAnnotation(value = "大西瓜")
class Person{}

对于 JDK 8 以前,只能是以下操作

public @interface MyAnnotation{
	String value() default "hi";   
}
public @interface MyAnnos{
	MyAnnotation[] value();   
}

//不需要二者的 生命周期@Retention、适用范围@Target 保持一致
@MyAnnos({@MyAnnotation(value = "小草莓"),@MyAnnotation(value = "大西瓜")})
class Person{}

6、JDK8新特性:类型注解

7、小结

  1. JDK内置三个基本注解
    1. @Override
    2. @Deprecated
    3. @SuppressWarning
  2. 自定义注解
    1. 步骤:
      1. 注解声明为@interface
      2. 内部定义成员,通常使用value表示
      3. 可以指定成员的默认值,使用default定义
      4. 如果注解没有成员,表示是一个标识作用,如@Override@Serializable
    2. 注意:
      1. 如果注解有成员,需要指定成员的值,要么默认值,要么自己赋值
      2. 自定义注解必须配上注解的信息处理流程(使用反射)才有意义
      3. 自定义注解继承了java.lang.Annotation接口
      4. 自定义注解一般都会指明两个元注解:@Retention、@Target
  3. JDK中四个元注解
    1. @Retention:指定 Annotation 的生命周期。只有声明为RUNTIME的注解,才可以通过反射获取
    2. @Target:用于指定该注解能用于修饰哪些元素
    3. @Document:用于指定该注解将被 javadoc 提取成文档的时候,将注解保留在文档中
    4. @Inherited:指明该注解具有继承性,父类有该注解,子类自动继承该注解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值