java自定义注解例子

本文详细介绍了Java自定义注解的分类、元注解以及如何创建和使用自定义注解。内容涵盖SOURCE、CLASS、RUNTIME三种运行机制,以及注解的默认值和获取注解的方法。通过Name、Gender、Profile等注解实例,展示了如何在Person类中应用和测试注解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java自定义注解
1.注解分类:
按运行机制分:

SOURCE源码注解:注解只在源码中存在,编译成.class文件就不存在了
CLASS编译时注解:注解在源码和.class文件都存在,但运行时会被移除
(@Override,@Deprecated,@SuppressWarnings)
RUNTIME运行时注解:表示这个注解会保留到运行时,甚至还会影响运行逻辑
(@Autowired)

按来源分:

内置注解(@Override,@Deprecated,@SuppressWarnings)
第三方注解
自定义注解

2.元注解(注解的注解):

@Retention
定义注解的生命周期,可选值为source、class、runtime
@Documented
文档化注解,会被javadoc工具文档化
@Inherited
注解是自动继承的,想让一个类和它的子类都包含某个注解,就可以使用它来修饰注解
@Target
Target通过ElementType来指定注解可使用范围的枚举集合
ElementType的用法

取值注解使用范围
METHOD可用于方法上
TYPE可用于类、接口、注解类型或枚举类型
ANNOTATION_TYPE可用于注解类型上(被@interface修饰的类型)
CONSTRUCTOR可用于构造方法上
FIELD可用于域上
LOCAL_VARIABLE可用于局部变量上
PACKAGE用于记录java文件的package信息
PARAMETER可用于参数上
3. 自定义注解例子:

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

自定义注解格式:
public @interface 注解名{注解体}
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
Annotation类型里面的参数该怎么设定:
第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;  
第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子Name注解就只有一个参数成员。
注解元素的默认值
注解元素注意点:
注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯

1.Name.java(姓名注解)
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;

/**
 * 
 * @description:姓名注解
 * @author: libl
 * @date: 2018年5月12日
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Name {
	String value() default "";
}

2.Gender.java(性别注解)
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;

/**
 * @description:性别注解
 * @author: libl
 * @date: 2018年5月12日
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Gender {

	public enum GenderType {

		Male("男"), Female("女"), Other("中性");

		private String genderStr;

		private GenderType(String arg0) {
			this.genderStr = arg0;
		}

		@Override
		public String toString() {
			return genderStr;
		}
	}

	GenderType gender() default GenderType.Male;

}

3.Profile.java(基本资料注解)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 
 * @description:基本资料注解
 * @author: libl  
 * @date: 2018年5月12日
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Profile {
	/**
     * ID
     *
     * @return
     */
    public int id() default -1;
 
    /**
     * 身高
     *
     * @return
     */
    public int height() default 0;
 
    /**
     * 籍贯
     *
     * @return
     */
    public String nativePlace() default "";
}

4.Person.java(使用注解)
/**
 * 
 * @description:使用自定义注解
 * @author: libl
 * @date: 2018年5月12日
 */
public class Person {
	@Name("李保磊")
	private String name;

	@Gender(gender = Gender.GenderType.Male)
	private String gender;

	@Profile(id = 1001, height = 180, nativePlace = "CN")
	private String profile;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getProfile() {
		return profile;
	}

	public void setProfile(String profile) {
		this.profile = profile;
	}
}

接口提供了以下四个方法来访问Annotation的信息:
方法1:< T extends Annotation > T getAnnotation(Class< T > annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
方法3:boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

5.TestUtils.java(测试注解)
import java.lang.reflect.Field;

/**
 * 
 * @description:注解测试
 * @author: libl
 * @date: 2018年5月12日
 */
public class TestUtils {

	public static void main(String[] args) {
		TestUtils.getInfo(Person.class);
	}

	public static void getInfo(Class<?> clazz) {
		String name = "";
		String gender = "";
		String profile = "";
		Field fields[] = clazz.getDeclaredFields();
		for (Field field : fields) {
			if (field.isAnnotationPresent(Name.class)) {
				Name arg0 = field.getAnnotation(Name.class);
				name = name + arg0.value();
				System.out.println("name=" + name);
			}
			if (field.isAnnotationPresent(Gender.class)) {
				Gender arg0 = field.getAnnotation(Gender.class);
				gender = gender + arg0.gender().toString();
				System.out.println("gender=" + gender);
			}
			if (field.isAnnotationPresent(Profile.class)) {
				Profile arg0 = field.getAnnotation(Profile.class);
				profile = "[id=" + arg0.id() + ",height=" + arg0.height() + ",nativePlace=" + arg0.nativePlace() + "]";
				System.out.println("profile=" + profile);
			}
		}
	}
}


运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值