【Java基础】——注解

注解相当于一个标签,可以给这个标签上添加相关信息,然后插入到代码中,在运行该程序时,虚拟机会利用反射机制来处理这些代码,使它完成相应的功能。它可以出现在许多地方,比如说包、类、接口、方法、构造器、实例域、局部变量、参数变量、类型参数等,通常可以这样自定义一个注解:以@interface声明一个注解,配置相关元注解,包括@Target来定义该注解适用的场合,@Retention来指明该注解保留多长时间,再配置一些参数;然后再添加一个方法去处理这个注解:先通过.getClass()方法获取Class对象,然后根据这个Class对象获得域、方法、构造器等;假如说我们限制获得了Class对象的域,那么就遍历所获得的域数组,获取域上的注解,然后使用Java Field.get()取得对象的Field属性值,接着和注解的参数值做相应的操作

注解是那些插入到源代码中使用其他工具可以对其进行处理的标签,它是一种形式化的方法,可以方便地在代码中添加信息,这些注解本身不会做任何事情,它们只是存在于源文件中,虚拟机会在运行时利用反射机制来处理注解,使之完成相应的功能。
在Java中,注解可以被当作一个修饰符来使用,置于注解项之前,中间没有分号。
注解可以出现在许多地方:包、类(包括Enum)、接口(包括注解接口)、方法、构造器、实例域(包括Enum常量)、局部变量、参数变量、类型参数
Java SE在java.lang、java.lang.annotationjavax.annotation包中定义了大量的注解接口。其中四个是元注解,用于描述注解接口的行为属性,其他的三个是规则接口,可以用它们来注解你的源代码中的项

标准注解

注解接口应用场合目的
@Deprecated全部将项标记为过时的
@SuppressWarnings除了包和注解之外的所有情况阻止某个给定类型的警告信息
@SafeVarargs方法和构造器断言varargs参数可安全使用
@Override方法检查该方法是否覆盖了某一个超类方法
@FunctionalInterface接口将接口标记为只有一个抽象方法的函数式方法
@PostConstruct方法将标记的方法应该在构造之后立即被调用
@PreDestroy方法将标记的方法应该在移除之前立即被调用
@Resource类、接口、方法、域在类或接口上:标记为在其他地方要用到的资源。在方法或域上:为注入而标记
@Resources类、接口一个资源数组
@Generated全部
@Target注解指明可以应用这个注解的那些项
@Rentention注解指明这个注解可以保留多久
@Document注解指明这个注解应该包含在注解项的文档中
@Interited注解指明当这个注解应用于一个类时,能够自动被它的子类继承
@Repeatable注解指明这个注解可以在同一个项上应用多次

元注解
@Target元注解可以应用于一个注解,以限制该注解可以应用到哪些项上

@Target({ElementType.TYPE, ElementType.METHOD})
public @interface BugReport

@Target元注解的元素类型

元素类型注解适用场合
ANNOTATION_TYPE注解类型声明
PACKAGE
TYPE类(包括Enum)及接口(包括注解类型)
METHOD方法
CONSTRUCTOR构造器
FIELD成员域(包括Enum常量)
LOCAL_VARIABLE局部变量
TYPE_PARAMETER类型参数
TYPE_USE类型用法

一条没有@Target限制的注解可以应用于任何项上。编译器将检查是否将一条注解只应用到了某个允许的项上

@Retention元注解用于指定一条注解应该保留多长时间
用于@Retention注解的保留策略

保留规则描述
SOURCE不包括在类文件中的注解
CLASS包括在类文件中的注解,但是虚拟机不需要将它们载入
RUNTIME包括在类文件中的注解,并由虚拟机载入。通过反射API可获得它们

每个注解都必须通过一个注解接口来定义
@interface声明创建了一个真正的Java接口。处理注解的工具将接收那些实现了这个注解接口的对象

自定义注解
@Target(ElementType.METHOD)
public @interface Test {
String value() default “”;
}
每个注解都具有下面这种格式: @AnnotationName(elementName1=value1, elementName2=value2,...) 默认值并不是和注解存储在一起的;相反地,它们是动态计算而来的。
有两种特殊的快捷方式可以用来简化注解:
如果没有指定元素,要么是因为注解中没有任何元素,要么是因为所有元素都使用默认值,那么你就不需要使用圆括号了。
另外一种快捷方式是单值注解。如果一个元素具有特殊的名字value,并且没有指定其他元素,那么你就可以忽略掉这个元素以及等号
如果注解的作者将其声明为可重复的,那么你就可以多次重复使用同一个注解

对于类和接口,需要将注解放置在class和interface关键字的前面
@Entity public class User {...}
对于变量,需要将它们放在类型的前面
@SuppressWarnings(unchecked") List<User> users = ...;
泛化类或方法中的类型参数可以像下面这样被注解:
public class Cache<@Immutable V> {...}
注解类型用法:
声明注解提供了正在被声明的项的相关信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
定义注解:(以@interface声明一个注解,配置相关元注解,包括@Target来定义该注解适用的场合,@Retention来指明该注解保留多长时间,再配置一些参数)

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
	int max() default 0;
	int min() default 0;
	String descrption() default "";
}

注解使用:

public class AnnoationTest {
	@Test(min = 6, max = 10, descrption = "haha")
	private String name;

	@Test(min = 6, max = 10, descrption = "haha")
	private String password;

	public String getName() return name;

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

	public String getPassword() return password;

	public void setPassword(String password) this.password = password;
}

注解处理器以及测试主方法:
先通过.getClass()方法获取Class对象
根据这个Class对象获得域、方法、构造器等
假如说获得了Class对象的域,遍历所获得的域数组
获取域上的注解
Java Field.get()取得对象的Field属性值
和注解的参数值做相应的操作


import java.lang.reflect.Field;
 
public class TestUtil {
 
    public static void valid(Object obj) throws IllegalAccessException {
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field:fields){
            Test test = field.getAnnotation(Test.class);//获取属性上的@Test注解
            if(test != null){
                field.setAccessible(true);//设置属性可访问
 
                if("class java.lang.String".equals(field.getGenericType().toString())){//字符串类型的才判断长度
                    String value = (String)field.get(obj);
                    if(value != null && ((value.length() > test.max()) || value.length() < test.min())){
                        System.out.println(test.description());
                    }
                }
            }
        }
 
    }
 
    public static void main(String[] args){
        AnnoationTest annotation = new AnnoationTest();
        annotation.setName("abcefg");
        annotation.setPasdword("1234567890");
        try {
            valid(annotation);
        } catch (IllegalAccessException e) {
 
            e.printStackTrace();
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值