注解

注解

转载于: https://blog.csdn.net/h294590501/article/details/80739985

注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,
​
注解的作用:
1.给程序带入参数
2.取代一些属性文件文件
​
标记可以加在包、类,属性、方法,方法的参数以及局部变量上定义。

 

注解的应用场景

1. 重写父类方法时。
​
2. 运行一个无main的方法时,带有@Test的成员方法可以直接运行,无需main方法。
​
​
3. 框架中的配置。
现在框架都是基于注解的配置,简单方便。

 

常见注解

JDK中内置了很多注解,以下例举一些:
​
1. @author:用来标识作者名。
​
2. @version:用于标识对象的版本号,适用范围:文件、类、方法。
​
3. @Override :用来修饰方法声明,告诉编译器该方法是重写父类中的方法,
​
如果父类不存在该方法,则编译失败

 

自定义注解

//定义格式
public @interface 注解名{
    属性类型 属性名();
}
​
如:定义一个名为Book的注解
public @interface Book{
    String value();
}

注解的属性

1. 属性的作用
可以让用户在使用注解时传递参数,让注解的功能更加强大。
​
2. 属性的格式
格式1:数据类型 属性名();
格式2:数据类型 属性名()  default  默认值;
​
 
3. 属性定义示例
public @interface Student {
    String value();
    int age() default 44;
}

 

自定义注解的属性类型:

1.八种基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String 类型
3.枚举类型
4.注解类型
5.以上数据类型的一维数组类型

 

使用自定义注解

//使用注意事项
​
如果属性有默认值,则使用注解的时候,这个属性可以不用赋值。
​
如果属性有默认值,则使用注解的时候,这个属性如果赋值了,以赋值为准。
​
如果属性没有默认值,那么在使用注解时一定要给属性赋值。
​
默认情况下,一个注解是可以用在一个类的任意地方的。
比如说: 类上、方法上、形参上 . 如果需要限定注解的使用范围,那么需要使用上@target这个注解。
​
默认情况下注解的内容也只是保留到了源码上,一旦经过编译之后,注解的内容就消失了,并没有保留到class文件上。想要获取到注解的数据就必须要Runtime这种保留策略.

 

一个特殊的注解属性value

1. 当注解中只有一个属性且名称是value,在使用注解时给value属性赋值可以直接给
属性值,无论value是单值元素还是数组类型。
 
2. 如果注解中除了value属性还有其他属性,且至少有一个属性没有默认值,则在使
用注解给属性赋值时,value属性名不能省略

 

元注解

用来定义注解的注解。

 

元注解的作用

用来说明自定义注解的在类中出现的位置和生命周期。

 

常用元注解

@Target
作用:定义该注解用在哪个位置,如果不写,默认是类中任何地方都可以使用。
​
可选的参数值在枚举类ElemenetType中包括:
​
TYPE: 用在类,接口上
​
FIELD:用在成员变量上
​
METHOD: 用在方法上
​
PARAMETER:用在参数上
​
CONSTRUCTOR:用在构造方法上
​
LOCAL_VARIABLE:用在局部变量上
​
​
​
@Retention
作用:定义该注解的生命周期。
可选的参数值在枚举类型RetentionPolicy中包括:
SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了。
​
CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,这个是默认值。
​
RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该注解。

 

@Retention(value=RetentionPolicy.RUNTIME)//定义注解生命周期。
@Target(value={ElementType.FIELD,ElementType.METHOD})//定义注解使用位置。
public @interface Book {
    int id() default 88;//图书编号
    String author() default "小飞";//作者
    double price() default 88.88;//单价
}

 

解析注解

通过Java技术,在程序运行时,获取注解中所有属性的过程则称为解析注解。

 

与注解解析相关的接口

Anontation:所有注解类型的公共接口,类似所有类的父类是Object。
AnnotatedElement:定义了与注解解析相关的方法,
​
常用方法以下四个:
1. boolean isAnnotationPresent(Class annotationClass); 
判断当前对象是否有指定的注解,有则返回true,否则返回false。
​
2. T getAnnotation(Class<T> annotationClass); 
获得当前对象上指定的注解对象。
​
3. Annotation[] getAnnotations(); 
获得当前对象及其从父类上继承的所有的注解对象。
​
4. Annotation[] getDeclaredAnnotations();
获得当前对象上所有的注解对象,不包括父类的。

获取注解对象

注解作用在那个成员上,就通过反射获得该成员的对象来得到它的注解。
//获取类的Class对象
Class clazz = 类名.class;
//获取private的id属性对象
Field f = clazz.getDeclaredField("id");
f.setAccessible(true);
//获取属性对象上是否有注解
 flag= f.isAnnotationPresent(Book.class);
//从属性对象上获取注解Book
book = f.getAnnotation(Book.class);
​
如注解作用在方法上,就通过方法(Method)对象得到它的注解
//获取类的Class对象
Class clazz = 类名.class;
// 得到方法对象
Method method = clazz.getDeclaredMethod("方法名",参数类型.class);
// 根据注解名得到方法上的注解对象
Book book = method.getAnnotation(Book.class);
​
如注解作用在类上,就通过Class对象得到它的注解
// 获得Class对象
Class c = 类名.class;
// 根据注解的Class获得使用在类上的注解对象
Book book = c.getAnnotation(Book.class);

获取注解对象上的数据

注解对象.注解属性名();
book.price();

 

使用反射获取注解的数据

@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD,ElementType.FIELD})
@interface Book {
​
    String value() default "book";
    String author() default "小芸";//作者
    double price() default 11.11;//单价
}
public class Demo {
​
    @Book(value="book001",author="李白",price=88)
    private int id;
​
    @Book(value="book002",author="诗仙",price=88)
    public void buy() throws Exception{
​
        //获取Test09的Class对象
        Class clazz = Demo.class;
​
        //获取public的buy方法
        Method m = clazz.getMethod("buy");
​
        //获取方法上是否有注解
        boolean flag = m.isAnnotationPresent(Book.class);
​
        //从方法上获取注解Book
        Book book = m.getAnnotation(Book.class);
​
        //获取注解Book中的所有属性了
        System.out.println(book.value());
        System.out.println(book.author());
        System.out.println(book.price());
        //上述代码叫反射注解
​
        //获取private的id属性对象
        Field f = clazz.getDeclaredField("id");
        f.setAccessible(true);
​
        //获取属性对象上是否有注解
         flag= f.isAnnotationPresent(Book.class);
​
        //从属性对象上获取注解Book
        book = f.getAnnotation(Book.class);
​
        //获取注解Book中的所有属性了
        System.out.println(book.value());
        System.out.println(book.author());
        System.out.println(book.price());
    }
​
    public static void main(String[] args) throws Exception {
        Demo test = new Demo();
       test.buy();
    }
}
​

 

模拟JUnit测试的@Test注释

public class Demo {
    public static void main(String[] args) throws Exception{
​
        //获取MyTestDemo类的Class对象
        Class clazz = MyTestDemo.class;
​
        //创建对象
        Object obj = clazz.newInstance();
​
        //获取public的方法
        Method[] ms = clazz.getMethods();
​
        //迭代
        for (Method m : ms) {
​
            //判断是否在运行时,看到方法上的注解@MyTest
            boolean flag = m.isAnnotationPresent(MyTest.class);
​
            //如果在运行时可见
            if(flag){
                //执行这个方法
                m.invoke(obj,null);
            }
        }
    }
}
/**
 * @MyTest注解
 */
@Retention(value= RetentionPolicy.RUNTIME)
@Target(value= ElementType.METHOD)
public @interface MyTest {
}
​
/**
 * 使用MyTest注解
 */
public class MyTestDemo {
    
    @MyTest
    public void test1(){
        System.out.println("public void test1()");
    }
    
    public void test2(){
        System.out.println("public void test2()");
    }
    
    @MyTest
    public void test3(){
        System.out.println("public void test3()");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值