0
点赞
收藏
分享

微信扫一扫

注解和自定义注解

求索大伟 2022-02-14 阅读 37

注解

注解相关

元注解meta-annotation

什么是元注解:基本注解,它能够应用到其它的注解上 用来解释其他注解 。譬如 --使用范围、注解保留的时间范围、注解继承性(子类是否继承父类的注解)等

@Retention 存活时间

Reteniton注解的作用: 描述注解保留的时间范围

public enum RetentionPolicy {
 
    SOURCE,    // 源文件保留
    CLASS,     // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}

@Documented 保存到javadoc

和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去

@Target 限定使用场景

Target 是目标的意思,@Target 指定了注解运用的地方。当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。
类比到标签,原本标签是你想张贴到哪个地方就到哪个地方,但是因为 @Target 的存在,它张贴的地方就非常具体了,比如只能张贴到方法上、类上、方法参数上等等。

@Target 有下面的取值:

  • ElementType.ANNOTATION_TYPE 给注解注解
  • ElementType.CONSTRUCTOR给构造方法注解
  • ElementType.FIELD 给属性注解
  • ElementType.LOCAL_VARIABLE 给局部变量注解
  • ElementType.METHOD 给方法注解
  • ElementType.PACKAGE 给包注解
  • ElementType.PARAMETER 给方法内的参数注解
  • ElementType.TYPE 给类型注解,比如类、接口、枚举

@Inherited 注解继承

Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation.
Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的 注解进行注解的话(真绕弯,就是说:@Inherited注解了B注解,B再注解别人),那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
说的比较抽象。代码来解释
自定义注解@Inherited实战

@Repeatable 重复

Repeatable 是可重复的意思。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。
什么样的注解会多次应用呢?通常是注解的值可以同时取多个
举个例子,一个人他既是程序员又是产品经理,同时他还是个画家。

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

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

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

自定义注解

什么是注解:实质上可以视为一种特殊的注释,如果没有解析它的代码,它并不比普通注释强。
自定义注解,新建一个@interface类,并加上元注解


@Target(ElementType.TYPE) //作用到类上
@Retention(RetentionPolicy.RUNTIME) // 在运行时有效
@Documented
@Inherited // 用@Huan注解过的子类 ,会怎样?  子类有其他注解后还会怎样?
public @interface Huan {
   String color() default "red";
}

测试解析注解:
AnnotationHuan类,使用@Huan注解

package com.chuliuhuan.annotation;

@Huan(color = "white")
public class AnnotationHuan {

}

解析AnnotationHuan 类

package com.chuliuhuan.test;

import com.chuliuhuan.annotation.AnnotationHuan;
import com.chuliuhuan.annotation.Huan;

import java.lang.annotation.Annotation;

/**
 * @author 褚留欢
 * @date 2021-06-01 8:33
 */
public class AnnotationTest {

	public static void main(String[] args) {
		// 如何注解类是 Huan注解
		/*
			当注解为:
			@Target(ElementType.TYPE)
			@Retention(RetentionPolicy.CLASS)
			@Documented
			zcls.isAnnotationPresent(Huan.class) 返回flase
			@Retention(RetentionPolicy.CLASS) 改成@Retention(RetentionPolicy.RUNTIME) 也走不进去
			搜了isAnnotationPresent 意思 发现isAnnotationPresent试用方法错误:
			A.isAnnotationPresent(B.class); 注释B是否在此A上。如果在则返回true;不在则返回false。
			因此B.isAnnotationPresent(B.class); X
		*/
		/*
		// 错误示例
			Class zcls= Huan.class;
			if (zcls.isAnnotationPresent(Huan.class)) {
				// 强转注解为 Huan类型
				Huan huan = (Huan) zcls.getAnnotation(Huan.class);
				System.out.println(huan.color());
			}
		*/
		//  获取AnnotationHuan的Class对象
		Class clsz = AnnotationHuan.class;
		// 判断AnnotationHuan类上是否有Huan注解
		if (clsz.isAnnotationPresent(Huan.class)) {
			//获取该类上Huan类型的注解
			Huan huan = (Huan) clsz.getAnnotation(Huan.class);
			System.out.println(huan.color());
		}
		/*
			//返回指定的注解
			getAnnotation
			//判断当前元素是否被指定注解修饰
			isAnnotationPresent
			//返回所有的注解
			getAnnotations
		 */
	}
}

自定义注解@Inherited 实战代码验证

为了更具体了解Inherited注解的作用,我们举个栗子看下

父类被修饰的注解有Inherited元注解,子类没有任何注解

// 父类

package com.chuliuhuan.annotation;

@Huan(color = "white")
public class AnnotationHuan {

}

// 子类

package com.chuliuhuan.annotation;

public class AnnotationHuanSubclass extends AnnotationHuan{

}

// 测试类,看AnnotationHuanSubclass 子类是否有Huan 注解

package com.chuliuhuan.test;

import com.chuliuhuan.annotation.AnnotationHuanSubclass;
import com.chuliuhuan.annotation.Huan;
/**
 * @author chuliuhuan
 * @date 2021-06-01 23:34
 */
public class AnnotationHuanSubclassTest {
	public static void main(String[] args) {
		Class<AnnotationHuanSubclass> annotationHuanSubclassClass = AnnotationHuanSubclass.class;
		if (annotationHuanSubclassClass.isAnnotationPresent(Huan.class)) {
			System.out.println("AnnotationHuanSubclass类上有Huan注解");
		}else{
			System.out.println("AnnotationHuanSubclass类上没有Huan注解==========NO=============");
		}
	}
}

控制台打印结:

C:\Users\哈哈\.jdks\adopt-openjdk-1.8.0_292\bin\java.exe ...
AnnotationHuanSubclass类上有Huan注解

Process finished with exit code 0

父类被修饰的注解有Inherited元注解,子类有其他任何注解(相同类型的其他注解)

子类、父类使用同一个有inherited性质的注解

// 新增一个其他注解
package com.chuliuhuan.annotation;

import java.lang.annotation.*;

/**
 * @author chuliuhuan
 * @date 2021-06-01 23:42
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HuanOther {
	String color() default "blue";
}


// 子类注解使用这新加的注解
package com.chuliuhuan.annotation;

/**
 * @author chuliuhuan
 * @date 2021-06-01 23:34
 */
@HuanOther
public class AnnotationHuanSubclass extends  AnnotationHuan{
}

// 测试这个注解

package com.chuliuhuan.test;

import com.chuliuhuan.annotation.AnnotationHuanSubclass;
import com.chuliuhuan.annotation.Huan;
import com.chuliuhuan.annotation.HuanOther;

/**
 * @author chuliuhuan
 * @date 2021-06-01 23:34
 */
public class AnnotationHuanSubclassTest {
	public static void main(String[] args) {
		Class<AnnotationHuanSubclass> annotationHuanSubclassClass = AnnotationHuanSubclass.class;
		if (annotationHuanSubclassClass.isAnnotationPresent(Huan.class)) {
			System.out.println("AnnotationHuanSubclass类上有Huan注解");
		}else{
			System.out.println("AnnotationHuanSubclass类上没有Huan注解==========NO=============");
		}
		if (annotationHuanSubclassClass.isAnnotationPresent(HuanOther.class)) {
			System.out.println("AnnotationHuanSubclass类上有HuanOther注解");
		}else{
			System.out.println("AnnotationHuanSubclass类上没有HuanOther注解******************NO***************");
		}

	}
}

控制台打印结果:

C:\Users\哈哈\.jdks\adopt-openjdk-1.8.0_292\bin\java.exe ...
AnnotationHuanSubclass类上有Huan注解
AnnotationHuanSubclass类上有HuanOther注解

Process finished with exit code 0

子类也使用该注解

子类、父类使用同一个有inherited性质的注解

自定义注解:
package com.chuliuhuan.annotation;

import java.lang.annotation.*;
/**
 * @author chuliuhuan
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Huan {
	String color() default "red";
	int age() default 18;
}

父类:

package com.chuliuhuan.annotation;

@Huan(color = "white",age = 24)
public class AnnotationHuan {

}

子类AnnotationHuanSubclass代码:

//使用相同类型的注解 并给注解属性设置初始值
package com.chuliuhuan.annotation;

/**
 * @author chuliuhuan
 * @date 2021-06-01 23:34
 */
@HuanOther
@Huan(color = "111111111111111")
public class AnnotationHuanSubclass extends  AnnotationHuan{
}

测试类:

// 测试Test类:
package com.chuliuhuan.test;

import com.chuliuhuan.annotation.AnnotationHuanSubclass;
import com.chuliuhuan.annotation.Huan;
import com.chuliuhuan.annotation.HuanOther;

/**
 * @author chuliuhuan
 * @date 2021-06-01 23:34
 */
public class AnnotationHuanSubclassTest {
	public static void main(String[] args) {
		Class<AnnotationHuanSubclass> annotationHuanSubclassClass = AnnotationHuanSubclass.class;
		if (annotationHuanSubclassClass.isAnnotationPresent(Huan.class)) {
			Huan annotation = annotationHuanSubclassClass.getAnnotation(Huan.class);
			System.out.println("color is ========>"+annotation.color());
			System.out.println("age is   ========>"+annotation.age());
			System.out.println("AnnotationHuanSubclass类上有Huan注解");
		}else{
			System.out.println("AnnotationHuanSubclass类上没有Huan注解==========NO=============");
		}
		if (annotationHuanSubclassClass.isAnnotationPresent(HuanOther.class)) {
			System.out.println("AnnotationHuanSubclass类上有HuanOther注解");
		}else{
			System.out.println("AnnotationHuanSubclass类上没有HuanOther注解******************NO***************");
		}

	}
}

单元测试结果:

C:\Users\哈哈\.jdks\adopt-openjdk-1.8.0_292\bin\java.exe ...
color is ========>111111111111111
age is   ========>18
AnnotationHuanSubclass类上有Huan注解
AnnotationHuanSubclass类上有HuanOther注解

Process finished with exit code 0

类A 、B为继承关系(A为父类,B为子类) ,注解C被@inherited 元注解修饰。
若A 使用@C且B不使用,那么B会继承A内的所有注解信息 ,例子: 父类使用有inherited性质的注解,子类没有使用
若A 使用@C且B也使用,那么B不继承A内的注解信息 例如: 子类、父类使用同一个有inherited性质的注解

举报

相关推荐

0 条评论