JavaSE基础十四-注解(Annotation)

注解概念理解参考:https://blog.csdn.net/briblue/article/details/73824058

https://blog.csdn.net/deskDopa/article/details/82557537

理解:

通俗的说,注解就是标签

注解可以在类加载,编译,运行时读取

自定义注解时,以@interface修饰符定义

Annotation接口是所有注解的父接口

 

在说注解之前,先说5个元注解!

一.5个元注解(对注解进行标记的标签,即注解的注解):

1.@Retention——注解生存期

取值如下:

RetentionPolicy.SOURCE    注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
RetentionPolicy.CLASS        注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME   注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
2.@Target——注解使用范围

注意:取值可以为数组,

@Target(value = {ElementType.FIELD, ElementType.METHOD})

单个值,

@Target(ElementType.FIELD)

取值如下:

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

3.@Documented——注解添加到API文档

4.@Inherited——在子类未使用注解的情况,将父类注解继承到子类 (就是让使用注解的类,在子类注解仍然起作用)

5.@Repeatable——重复注解,注解的值可以同时取多个         (注意:写该元注解来注解注解时,不要使用其他元注解)


@interface Persons {        //注解值容器
	Person[]  value();        
}


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


@Person(role="artist")    //取三个值
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
	
}

二.5个基本注解和自定义注解(基本注解是JDK已提供的):

1.@Override——标记方法重写

适用对象:方法

作用:主要可以检查编辑错误

2.@Deprecated——标记过时

适用对象:类,方法

3.@SuppressWarnings——阻止编译器警告

适用对象:所有

使用:@SuppressWarnings("unchecked")  ,关键字使用:

all取消所有警告
boxing 禁止与装箱/拆箱操作相关的警告
cast禁止与强制转换操作相关的警告
dep-ann禁止与废弃注释相关的警告
deprecation禁止与弃用相关的警告
fallthrough禁止与switch语句中丢失的中断相关的警告
finally 要抑制相对于最终阻塞的不返回的警告
hiding抑制相对于隐藏变量的局部变量的警告
incomplete-switch要禁止与switch语句中丢失的条目相关的警告(enum情况)
nls禁止与非nls字符串文字相关的警告
null抑制与空分析相关的警告
rawtypes在类参数上使用泛型时,禁止与非特定类型相关的警告
restriction禁止使用与禁止引用相关的警告
serial要禁用与可序列化类缺少serialVersionUID字段相关的警告
static-access禁止与不正确的静态访问相关的警告
synthetic-access 禁止与内部类的未优化访问相关的警告
unchecked抑制与未检查操作相关的警告
unqualified-field-access禁止与字段访问无关的警告
unused抑制与未使用代码相关的警告

4.@ SafeVarargs——参数安全注解(“堆污染”警告):比如:泛型堆污染,将不带泛型的对象赋给带泛型的对象

还有一种消除堆污染方式:@SuppressWarnings("unchecked") 

5.@FunctionInterface——函数式接口注解

函数式接口(只有一个抽象方法的接口)

作用:告诉编译器检查接口为函数式接口,编程时可以转化为Lambda表达式

 

自定义注解:定义注解时定义注解参数,使用注解时确定参数值

注解分为:

1.标识注解:就是定义注解没有参数(成员变量),比如@Override,@Deprecated...

2.元数据:定义注解包含参数(成员变量)(若参数只有一个,只能命名value())

package com.hw.writeannotion;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
public @interface CustomAnnotation{
    //定义注解参数:注解参数类型 + 注解参数名();
    //有默认值,在使用注解时可以不赋值
    String name() default "我是默认";
    int age() default 100;
}





package com.hw.writeannotion;

@CustomAnnotation(name = "pp",age = 20)
class Test {

}


可以,注解定义好了,而且使用了,可是不能生效。!!!

这需要相关工具提取并处理注解信息

三.提取注解信息:

提取注解信息,需要通过Java5在Javalang.reflect包新增的AnnotatedElement接口的实现类(Class,Constructor,Field,Method,Package)来提取信息。

AnnotatedElement接口:

AnnotatedElement接口实现方法:

判断该对象是否应用了某个注解:

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}

获取该对象的指定类型注解:

public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}

获取该对象的所有注解:

public Annotation[] getAnnotations() {}

获取指定程序元素的注解:

<T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)

获取指定程序元素的所有注解:

Annotation[] getDeclaredAnnotations() {}

获取@Repeatable重复注解下的注解:

<T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)

获取@Repeatable重复注解下的所有注解:

<T extends Annotation> T[] getDeclaredByType(Class<T> annotationClass)

 

但是,要使用这些实现类的方法,必须通过反射获取对象!

 

实例:

提取元数据信息name,age:

package com.hw.writeannotion;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME) //最好自定义注解时把可能用到的元注解都加上,避免获取不到注解
@Target(ElementType.METHOD)
@Documented
public @interface CustomAnnotation{
    String name() default "我是默认";
    int age() default 100;
}



package com.hw.writeannotion;

public class Test {

    @CustomAnnotation(name = "pp",age = 20)
    public void info() {
    }
}



//提取注解信息
package com.hw.writeannotion;

import java.lang.annotation.Annotation;

public class MainTest {

    public static void main(String[] args) throws NoSuchMethodException {
        boolean b = Test.class.getMethod("info").isAnnotationPresent(CustomAnnotation.class);
        if (b){
            Annotation[] t = Test.class.getMethod("info").getAnnotations();
            for (Annotation tt: t) {
                if (tt instanceof CustomAnnotation)
                    System.out.println(((CustomAnnotation) tt).name());
                    System.out.println(((CustomAnnotation) tt).age());
            }
        }
    }
}

结果:

pp
20

提取注解信息更多参考:

@TestAnnotation(msg="hello")
public class Test {
	
	@Check(value="hi")
	int a;
	
	
	@Perform
	public void testMethod(){}
	
	
	@SuppressWarnings("deprecation")
	public void test1(){
		Hero hero = new Hero();
		hero.say();
		hero.speak();
	}


	public static void main(String[] args) {
		
		boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
		
		if ( hasAnnotation ) {
			TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
			//获取类的注解
			System.out.println("id:"+testAnnotation.id());
			System.out.println("msg:"+testAnnotation.msg());
		}
		
		
		try {
			Field a = Test.class.getDeclaredField("a");
            //我们不能直接操作私有属性,需要关闭程序安全检测
			a.setAccessible(true);
			//获取一个成员变量上的注解
			Check check = a.getAnnotation(Check.class);
			
			if ( check != null ) {
				System.out.println("check value:"+check.value());
			}
			
			Method testMethod = Test.class.getDeclaredMethod("testMethod");
			
			if ( testMethod != null ) {
				// 获取方法中的注解
				Annotation[] ans = testMethod.getAnnotations();
				for( int i = 0;i < ans.length;i++) {
					System.out.println("method testMethod annotation:"+ans[i].annotationType().getSimpleName());
				}
			}
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e.getMessage());
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e.getMessage());
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e.getMessage());
		}
		
		

	}

}

结果:

id:-1
msg:hello
check value:hi
method testMethod annotation:Perform

注解实践:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值