注解【定义+使用+读取】

注解的概述

注释你还记得么?开个玩笑而已!
注释是给人看的,而注解是给程序看的!
注释是用来替代配置文件的!你回忆一下,我们以前总是要写一些配置文件,例如web.xml你还记得么?里面要写<servlet><servlet-mapping>!谁来读配置文件呢?当然是Tomcat!谁来写配置文件呢?当然是我们来写了!

在Servlet3.0中就可以使用使用注解来代替配置文件,开发者就不用再写配置文件了,而是写注解,然后Tomcat来读取注解。

注解也是类,需要定义了才能使用!
分别在Servlet3.0中有一个注解类为@WebServlet,然后我们就可以在Servlet中使用@WebServlet中使用这个注解了。这个注解就是用来替代<servlet>了。然后Tomcat会通过反射来读取注解中的信息!

Java中的注解

Java中的注解:

  • @Overrid:作用在方法上的注解。当方法不是重写父类的方法时会报错;
  • @Deprecated:作用在方法上。标记该方法为作废方法(已过时);
  • @SuppressWarnings:作用在方法上,压制警告。

定义注解类

定义注解类不能使用class、enum,也不能使用interface,而是使用@interface。

public @interface MyAnn{}

使用注解目标

注解可以作用在:类(接口或枚举)、属性、方法、构造器、包、参数、局部变量

package cn.itcast.annocation;

@MyAnn
public class MyClass {
    @MyAnn
    private int a;
    @MyAnn
    public MyClass() {}
    @MyAnn
    public void fun1() {}
    @MyAnn
    public void fun2(@MyAnn String s) {
        @MyAnn
        int n = 10;
    }
}

注解的属性

定义注解时也可以给出属性,注意,属性的权限默认为public 并且,必须是public。

public @interface MyAnn  {
    /**
    * 定义了两个属性
    */
    String value();
    int value1();
}

其中value就是属性!你可能会说,它是一个方法!没错,它是一个方法,但我们非要称之为属性,因为把它当做属性更加好理解。

当为注解指定属性后,那么在使用注解时就必须要给属性赋值了:

/**
* 在使用注解时需要给属性赋值
*/
@MyAnn(value1=100,value="hello") 
public class MyClass {
}

注解的属性还可以有默认值,在使用注解时就可以不给带有默认值的属性赋值了。但没有给出默认值的属性还是要赋值的。

public @interface MyAnn {
    /**
    * value是带有默认值的属性
    */
    String value() default "hello world"; 
    int value1();
}
/**
* 在使用注解时,没有给出value属性,因为它有默认值,可以不赋值。
* 但value1没有默认值就必须赋值。
* 当然也可以给带有默认值的属性赋值。
*/
@MyAnn(value1=100) 
public class MyClass {
}

在使用注解时,如果只给名为value的属性赋值,那么可以不给出属性的名称直接给出值。

public @interface MyAnn {
    String value() default "hello world";
    int value1() default 100;
}
/**
* 因为所有属性都有默认值,所以没问题。
*/
@MyAnn() 
    public class MyClass {
}
/**
* 因为所有属性都有默认值,所以可以把注解后面的圆括号省略。
*/
@MyAnn
    public class MyClass {
}
/**
* 给value属性赋值
*/
@MyAnn(value="hello") 
    public class MyClass {
}
/**
* 给value1属性赋值
*/
@MyAnn(value1=200) 
    public class MyClass {
}
/**
* 给value和value1属性赋值
*/
@MyAnn(value="hello",value1=200) 
    public class MyClass {
}
/**
* 因为没有给出属性名称,那么就是给value属性赋值
*/
@MyAnn("hello annocation") 
    public class MyClass {
}
/**
* 因为value属性是String类型的,所以出错!
*/
@MyAnn(300) 
    public class MyClass {
}
/**
* 出错!因为不是给一个属性赋值,那么这时就不能再省略属性的名字。
*/
@MyAnn("hello",value1=200) 
    public class MyClass {
}

注解的作用目标

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


在定义注解时可以限制注解的作用目录!例如让注解只能作用在类和方法上。
这需要使用元注解:@Target。该注解有一个属性value,类型为ElementType[],它是枚举类型。

public @interface Target {
    ElementType[] value();
}
public enum ElementType {
  TYPE,FIELD,METHOD,PARAMETED,CONSTRUCTOR,LOCAL_VARIABLE,ANNOCATION_TYPE,PACKAGE
}

在定义注解时,可以使用@Target注解来限制注解的作用目标:

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

这样MyAnn就只能作用在类和方法上的!其中ElementType.TYPE表示类和接口。

@MyAnn()
public class MyClass {
    /**
    * 出错!因为MyAnn被限制只能作用在类和方法上,不能作用在属性上。
    */
    @MyAnn() 
    private int a;

    @MyAnn()
    public void fun() {}
}

注解的保留策略

注解的保留策略是指,注解是只保留在源代码上,还是保留到class文件上,再或者是类在运行时,可以被类加载器加载到JVM内存中。

如果希望注解被反射,那么注解就要保留到运行时,而不是源代码或类文件上。

指定注解的保留策略需要使用元注解@Retention,它有一个value属性,类型为RetentionPolicy类型,RetentionPolicy是枚举类型:

public @interface Retention {
    RetentionPolicy value();
}
public enum RetentionPolicy {
    SOURCE, CLASS, RUNTIME
}

下面代码是指定注解保留到运行时

//注解保留到运行时
@Retention(RetentionPolicy.RUNTIME) 
//注解可以作用在类或方法上
@Target({ElementType.TYPE, ElementType.METHOD}) 
public @interface MyAnn {
    //String类型的value属性,默认值为hello
    String value() default "hello"; 
    //int类型的value1属性,默认值为100
    int value1() default 100; 
}

通过反射读取注解

读取注解需要使用反射来完成

/**
* 保留到运行时,如果不设置为保留到运行时,那么就无法反射出来
*/
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnn {
    String value() default "hello";
    int value1() default 100;
}
@MyAnn(value="hello world", value1=200)
public class MyClass {
    private int a;
    //给value属性赋值
    @MyAnn("myMethod") 
    public void fun() {}
}
public class Demo1 {
    public static void main(String[] args) throws Exception {
        Class clazz = MyClass.class;
        //获取类上的MyAnn类型的注解
        MyAnn myAnn = (MyAnn) clazz.getAnnotation(MyAnn.class); 
        //获取value()属性值
        System.out.println(myAnn.value()); 
        //获取value1属性值
        System.out.println(myAnn.value1()); 

        Method method = clazz.getMethod("fun");
        //获取方法上的MyAnn类型的注解
        MyAnn myAnn1 = method.getAnnotation(MyAnn.class); 
        System.out.println(myAnn1.value());
        System.out.println(myAnn1.value1());
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值