Java 注解

目录

1、简述

2、元注解

@Target

@Retention

@Documented

@Inherited

@Repeatable

3、常用注解

4、自定义注解

5、示例

1、简述

    注解(Annotation)是JDK5.0中引入的新特性。那么什么是注解呢?官方解释是:注解是一系列元数据,用于解释程序代码,可修饰类、方法、变量等,对修饰的代码没有直接影响。用比较通俗的话语来说,注解就是代码中的特殊标记,用于修饰代码(类,方法,变量等),并且对代码的运行效果没有直接影响。那么注解修饰代码有什么作用呢? 首先,注解可以提供信息给开发工具(编译器)用于检测错误或警告信息等;其次,在编译期,开发工具可以通过注解信息生成html文档或者做其他处理;最后,在运行前,可以利用反射机制获取注解的内容。当然这几个时期可以通过元注解设置,如果注解设置为源码期,则编译和运行时期就不会有注解信息,同理注解使用时期设置的是编译期的,则在运行期就获取不到注解信息。注解在平时后台开发,框架和jdk源码中都比较常见的,理解了注解,在后续的开发或学习源码时是特别有用的。

2、元注解

    理解了注解概念,那么什么是元注解呢?通俗的说就是修饰注解的注解就叫做元注解,Java中的元注解有以下几个,分别为@Target,@Retention,@Documente,@Inherited,@Repeatable(JDK1.8引入的)。下面介绍下这几个元注解:

@Target

    描述了注解应该用于什么地方,即使用范围。取值在java.lang.annotation.ElementType 枚举类中,分别为:

  • TYPE:类,接口(包括注释类型)或枚举声明   
  • FIELD:字段声明(包括枚举常数) 
  • METHOD:方法声明
  • PARAMETER:正式参数声明
  • CONSTRUCTOR:构造函数声明 
  • LOCAL_VARIABLE:局部变量声明
  • ANNOTATION_TYPE:注解类型声明  
  • PACKAGE:包声明
// 表示此注解可以修饰类,接口,方法,构造方法,不能修饰其他
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
@interface MyAnnotationOne {
}

// 表示此注解只能用于方法,不能修饰其他
@Target({ElementType.METHOD})
@interface MyAnnotationTwo {
}

@MyAnnotationOne
class Person {
	@MyAnnotationTwo
	public void fun() { }
}

@Retention

    描述了被修饰注解使用的生命周期,注解的只取RetentionPolicy枚举类,值如下:

  • SOURCE:表示注解只存在于源码时期,编译的class文件中就没有此注解了。
  • CLASS:表示注解存在于编译期。
  • RUNTIME:表示注解存在于运行期,在运行期还可通过反射机制获取注解的值。
@Retention(value=RetentionPolicy.SOURCE)
@interface MyAnnotationOne {
}

// 此处value= 可以省略
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotationTwo {
}

@Documented

    这个注解说明了被修饰的注解可以被文档化,这是一个标记注解,标记注解就是没有成员的注解。

@Inherited

    这个注解也是个标记注解,字面意思是继承的意思,它说的是如果某个类A(非接口)被@Inherited注解修饰的注解B所修饰,则类A的子类自动继承了注解B。

@Repeatable

    这个注解是在JDK1.8引入的,是重复的意思。怎么用呢?例如,在一个管理系统中,角色可能有管理员,教师,指导员,导师,学生等,某个人可能有其中几个角色,我们需要通过注解的方式来实现,那么此时就可以用@Repeatable注解,示例如下:

public class RepeatableTest {
	public static void main(String[] args) {
		Class<User> manClass = User.class;
		boolean flag = manClass.isAnnotationPresent(UserRoles.class);
		if (flag) {
			UserRoles userRoles = (UserRoles) manClass.getAnnotation(UserRoles.class);
			for (Role role : userRoles.value()) {
				System.out.println(role.roleName());
			}
		}
	}
}

@Repeatable(UserRoles.class)
@interface Role {
	String roleName() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface UserRoles {
	Role[] value();
}

@Role(roleName="admin")
@Role(roleName="tutor")
class User { }

3、常用注解

    Java还提供了几个常用的注解,有@Override,@Deprecated,@SuppressWarnings等等。

  • @Override:指的是重写,基本上在子类重写父类方法时会使用,子类方法用了此注解,但方法名和父类不同时,IDE工具基本都会做错误提示的。
  • @Deprecated:指的是废弃,一般JDK源码中非常常见,例如某个方法过时了,此时会用此注解,提示开发者,此方法过时了,不要再用了(实际上还可以用,但建议不要使用过时的方法)。
  • @SuppressWarnings:指的是忽视警告,例如使用了废弃的方法,实现了Serializable但未生成serialVersionUID,IDE工具都会做提示,此时使用此注解可以忽略警告。

4、自定义注解

    有时候我们需要使用注解,但现有的注解又无法满足要求,则可以自定义注解。自定义注解有以下几个规则:

  • 自定义注解格式为:修饰符 @interface 注解名 { 注解体 },注解体的格式为:修饰符 类型 成员名() default 成员默认值;
  • 注解可以没有注解体,此时注解为标记注解,只起标记作用;成员可以没有默认值。
  • 注解和成员的修饰符只能为public或默认访问权限。
  • 成员类型只能为基本数据类型、数组、String、枚举,类等数据类型,不能为自定义数据类型。
  • 获取注解信息需要通过反射机制获取。

5、示例

    下面通过一个简单的示例来学习下自定义注解(示例中用到了反射,不了解反射机制的先看下:https://blog.csdn.net/lanmuhhh2015/article/details/102462338):

package com.base.annotation;

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;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class CustomAnnotation {
	public static void main(String[] args) throws Exception {
		Class<?> userClass = Class.forName("com.base.annotation.User");
		// 获取类的相关注解值
		getClassAnnotationVal(userClass);
		// 获取类中方法的相关注解值
		getMethodAnnotationVal(userClass);
		// 获取类中属性的相关注解值
		getFieldAnnotationVal(userClass);
	}

	private static void getClassAnnotationVal(Class<?> obj) {
		String className = obj.getName();
		// 获取类的AuthorAnnotation注解值
		boolean isHaveAnn = obj.isAnnotationPresent(AuthorAnnotation.class);
		if (isHaveAnn) {
			AuthorAnnotation author = obj.getAnnotation(AuthorAnnotation.class);
			System.out.println(className + ":" + author.name());
		}
		// 获取类的DescriptionAnnotation注解值
		isHaveAnn = obj.isAnnotationPresent(DescriptionAnnotation.class);
		if (isHaveAnn) {
			DescriptionAnnotation des = obj.getAnnotation(DescriptionAnnotation.class);
			System.out.println(className + ":" + des.value());
		}
	}
	
	private static void getMethodAnnotationVal(Class<?> obj) {
		Method[] methods = obj.getDeclaredMethods();
		boolean flag = false;
		for (Method method : methods) {
			String methodName = method.getName();
			flag = method.isAnnotationPresent(AuthorAnnotation.class);
			if (flag) {
				AuthorAnnotation ann = method.getAnnotation(AuthorAnnotation.class);
				System.out.println(methodName+":"+ann.name());
			}
			
			flag = method.isAnnotationPresent(DescriptionAnnotation.class);
			if (flag) {
				DescriptionAnnotation des = method.getAnnotation(DescriptionAnnotation.class);
				System.out.println(methodName+":"+des.value());
			}
		}
	}
	
	private static void getFieldAnnotationVal(Class<?> obj) {
		Field[] fields = obj.getDeclaredFields();
		boolean flag = false;
		for (Field field : fields) {
			String fieldName = field.getName();
			flag = field.isAnnotationPresent(AuthorAnnotation.class);
			if (flag) {
				AuthorAnnotation ann = field.getAnnotation(AuthorAnnotation.class);
				System.out.println(fieldName+":"+ann.name());
			}
			
			flag = field.isAnnotationPresent(DescriptionAnnotation.class);
			if (flag) {
				DescriptionAnnotation des = field.getAnnotation(DescriptionAnnotation.class);
				System.out.println(fieldName+":"+des.value());
			}
		}
	}
}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface AuthorAnnotation {
	String name() default "zhangsan";
}

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface DescriptionAnnotation {
	String value();
}

@AuthorAnnotation
@DescriptionAnnotation("this is a user class")
class User {
	@DescriptionAnnotation("this is userName field")
	private String userName;

	@AuthorAnnotation(name="lisi")
	@DescriptionAnnotation("this is getUserName function")
	public String getUserName() {
		return userName;
	}
	
	@AuthorAnnotation(name="wangwu")
	@DescriptionAnnotation(value="this is setUserName function")
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

运行结果:

com.base.annotation.User:zhangsan
com.base.annotation.User:this is a user class
getUserName:lisi
getUserName:this is getUserName function
setUserName:wangwu
setUserName:this is setUserName function
userName:this is userName field

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值