java注解及自定义注解的一次学习

从JDK1.5开始,引入了源代码中的注解机制。鉴于目前大部分框架(Spring)都使用了注解简化代码并提高编码的效率,因此掌握并深入理解注解对于一个java工程师来说是很有必要的事。

元数据

描述数据的数据

1. 注解和注释的区别

注释注解
提供代码功能的说明(描述作用)实现程序功能的重要组成部分
不会被程序所读取可以在编译、类加载、运行时被读取,并执行相应处理

2. 注解分类

2.1 内建注解(基本注解)

java.lang包中,都继承自java.lang.annotation.Annotation

注解描述作用
@Override限定重写父类方法方法
@Deprecated标记已过时方法、包、属性、构造方法、局部变量、参数、类
@SuppressWarnings抑制编译器警告(消除警告信息)诸如使用泛型类提示方法、属性、构造方法、局部变量、参数、类

在这里插入图片描述

@SuppressWarnings注解的参数

参数作用
deprecation使用了过时的程序元素
unchecked执行了未检查的转换
unused有程序元素未被使用
fallthroughswitch程序块直接通往下一种情况而没有break
path在类路径中有不存在的路径
serial在可序列化的类上缺少serialVersionUID定义
finally任何finally子句都不能正常完成
all所有情况

比如:

在这里插入图片描述

在这里插入图片描述

2.2 元注解

java为注解提供了4种注解。也就是说:

  • 注解:对类、方法、接口进行注解
  • 元注解:对注解进行注解
注解描述
@Target用于指定被修饰的注解能用于修饰哪些程序元素
@Retention用于指定被修饰的注解可以保留多长时间
@Documented使用了此注解的彼注解,在彼注解修饰的程序的API文档中将包含彼注解说明
@Inherited默认情况下,父类的注解不被子类继承,如果想要继承父类注解,就必须使用此注解
  1. @Target

    该注解具有value属性,被该注解修饰的注解只能用来注解对应的目标。

    属性值描述
    ElementType.ANNOTATION_TYPE注解类型声明
    ElementType.CONSTRUCTOR构造方法声明
    ElementType.FIELD字段声明(包括枚举常量)
    ElementType.LOCAL_VARIABLE局部变量声明
    ElementType.METHOD方法声明
    ElementType.PACKAGE包声明
    ElementType.PARAMETER参数声明
    ElementType.TYPE类、接口(包括注解类型)或枚举声明

在这里插入图片描述

  1. @Retention

    如果注解定义中不存在此元注解,则保留策略默认为RetentionPolicy.CLASS

    此注解包含一个RetentionPolicy类型的value属性,使用此注解必须指定value值

    属性值描述
    RetentionPolicy.CLASS编译器将把注解记录在class文件中,当运行java程序时,虚拟机不再保留注解
    RetentionPolicy.RUNTIME编译器将把注解记录在class文件中,当运行java程序时,虚拟机八六注解,程序可以通过反射获取该注解
    RetentionPolicy.SOURCE编译器将直接丢弃被修饰的注解

2.3 自定义注解

自定义注解想起作用,必须使用元注解修饰。

2.3.1 注解语法

@Target(ElementType.METHOD)
@interface MyAnnotation

自定义注解可以定义属性,以无参方法的形式声明,如:

@Target(ElementType.METHOD)
@interface MyAnnotation{
	//定义一个属性value
	String value();
}

可以按如下格式使用MyAnnotation注解:

public class Test{
    //如果没有写属性名,而这个注解又有value值,则将这个值赋给value属性
    //@MyAnnotation("good")
    @MyAnnotation(value="good")
    public void getObjectInfo(){
    }
}

可以修改自定义注解MyAnnotation包含两个属性,并赋默认值,如:

@Target(ElementType.METHOD)
@interface MyAnnotation{
	//定义两个属性name和age
	String name() default "张三";
	int age() default 22;
}

使用注解:

public class Test{
    //使用带属性的注解时,需要为属性赋值
    @MyAnnotation(name="李四",age=18)
    public void getObjectInfo(){
    }
}

使用带属性的注解时,需要给属性赋值。如果自定义注解给属性赋了默认值,则可使用不带属性值的注解,让注解使用自己的默认值。

2.3.2 注解使用形式

  • 不带参数:@Annotation,例如@Override
  • 带一个参数:@Annotation(参数),如@SuppressWarnings(value=“unused”)
  • 带多个参数:@Annotation({参数1,参数2,参数3…}),如@MyAnno(name=“xxx”,age=15)

2.3.3 记录一次自定义注解的使用----验证信息

使用场景:通过注解来进行验证和部署

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
*@author:秦淏
*@version:2020年12月11日
*@TODO:
*/
public class TestAnno {
	/*
	 * 三个成员属性
	 */
	@MyAnno
	private Integer id;
	private String name;
	private String path;
	/*
	 * 提供getter/setter 方法
	 */
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	/*
	 * 提供构造方法
	 */
	public TestAnno() {
		super();
		// TODO Auto-generated constructor stub
	}
	public TestAnno(Integer id, String name, String path) {
		super();
		this.id = id;
		this.name = name;
		this.path = path;
	}
	@Override
	@Deprecated
	@SuppressWarnings(value = { "unchecked","unused" })
	public String toString() {
		// TODO Auto-generated method stub
		return super.toString();
	}
	/*
	 * 验证数据完整性
	 */
	public static void main(String[] args) {
		//通过反射获取TestAnno类的所有属性
		Class<TestAnno> test = TestAnno.class;
		Field[] field = test.getDeclaredFields();
		//遍历所有属性
		for (int i = 0; i < field.length; i++) {
			//判断属性是否使用了MyAnno自定义注解
			if(field[i].getAnnotation(MyAnno.class)!=null) {
				//使用了注解即可继续下一个属性
				continue;
			}
			/*
			 * 没有使用MyAnno自定义注解的,判断是否存在对应的get方法
			 */
			String fie = field[i].getName().substring(0, 1).toUpperCase()+field[i].getName().substring(1);
			
			try {
				Method method = test.getMethod("get"+fie);
				
				if(method.invoke(test) == null) {
					System.out.println("数据不完整");
				}
				
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}
/*
 * 定义一个注解,只能使用在属性上,可以通过反射获取该注解
 */
@Target(ElementType.FIELD)
@interface MyAnno{}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值