举例讲解JDK注解的使用和自定义注解的方法

时间:2021-11-08 02:36:16

jdk中的三个基本注解

a、@override:检查子类确实是覆盖了父类的方法。
b、@deprecated:说明已经过时了。
c、@suppresswarnings({ "unused", "deprecation" }):抑制程序中的警告。unused警告的类型。{}数组。all抑制所有警告。

简单使用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class demo1 {
  //@suppresswarnings({ "deprecation", "unused" })
  @suppresswarnings("all")
  public void fun()
  {
    int i = 5;
    system.out.println("hello");
    system.out.println(new date().tolocalestring());
  }
}
class tests extends demo1
{
  @override
  public void fun()
  {
    super.fun();
  }
  @deprecated
  public void tt()
  {
    system.out.println(new date().tolocalestring());
  }
}

声明一个注解 @interface 注解名{}

?
1
public @interface myannotation{}

注解它的本质就是一个接口,这个接口需要继承 annotation接口。

?
1
2
public interface myannotation extends java.lang.annotation.annotation {
}

注解的属性类型:

  •     1.基本类型
  •     2.string
  •     3.枚举类型
  •     4.注解类型
  •     5.class类型
  •     6.以上类型的一维数组类型

具体是怎样定义的呢,我们看代码:

?
1
2
3
4
5
6
7
8
9
10
public @interface myanno1 {
  //注解中定义的都是属性
  int age() default 20;
  string[] name() default "hehe";
  string value() default "haha";
  love love();
  //myanno2 anno();
  //public static final int num = 5;//可以
  //public abstract void fun();//error
}

使用自定义注解:

?
1
2
3
4
5
6
7
8
public class demo2 {
  //@myanno1(age=25,name={"jack","lucy"},value="zhengzhi")
  //@myanno1(value="zhengzhi")
  @myanno1(value="zhengzhi",love=love.eat)
  public void tests()
  {
  }
}

如果在没有默认值的情况下,使用自定义注解我们需要设置注解中属性的值。

注解的反射:(灵魂)

?
1
2
3
4
5
6
7
8
9
10
模拟junit的@test
a、反射注解类
java.lang.reflect.annotatedelement:
<t extends annotation> t getannotation(class<t> annotationtype):得到指定类型的注解引用。没有返回null
annotation[] getannotations():得到所有的注解,包含从父类继承下来的。
annotation[] getdeclaredannotations():得到自己身上的注解。
boolean isannotationpresent(class<? extends annotation> annotationtype):判断指定的注解有没有。
class、method、field、constructor等实现了annotatedelement接口.
如果:class.isannotationpresent(mytest.class):判断类上面有没有@mytest注解;
method.isannotationpresent(mytest.class):判断方法上面有没有@mytest注解。

下面通过代码实现一下。

我们模拟实现@test注解的功能

首先这是我们的注解@mytest

?
1
2
3
4
5
6
7
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
//元注解: 用来注解注解的
@retention(retentionpolicy.runtime)
public @interface mytest {
  long timeout() default integer.max_value;//设置超时时间的
}

这是我们使用注解的类:

?
1
2
3
4
5
6
7
8
9
10
11
12
public class dbcrud {
  @mytest(timeout=1000000)
  public void addtest()
  {
    system.out.println("addtest方法执行了");
  }
  @mytest
  public void updatetest()
  {
    system.out.println("updatetest方法执行了");
  }
}

当我们使用了注解,我们就需要判该类是否使用了注解,我们通过反射来实现。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static void method1() throws illegalaccessexception,
    invocationtargetexception, instantiationexception {
    class claz = dbcrud.class;//得到字节码文件对象
    //得到该类及父类中的所有方法
    method[] methods = claz.getmethods();
    for(method m:methods){
      //判断方法是否使用了@mytest这个注解
//     boolean boo = m.isannotationpresent(mytest.class);
//     system.out.println(m.getname()+"===="+boo);//都是false 默认注解存活到 class,改变存活到runtime
      if(m.isannotationpresent(mytest.class)){
        m.invoke(claz.newinstance(), null);
      }
    }
  }

这里我们需要注意的是,我们需要考虑到自定义注解的存活范围。

默认的自定义注解只存活到编译时期,class阶段。

可以注意到,我们上面的自定义注解应用了@retention注解,这个注解就是改变自定义注解的存活范围。

这个注解也叫做元注解,只能用在注解上的注解叫做元注解。

上面的method方法没有考虑到超时的问题,下面我们再完善一下。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//method1();
    //反射解析注解的属性
    class claz = dbcrud.class;
    method[] methods = claz.getmethods();
    for(method m:methods){
      //从该方法上获取mytest注解
      mytest mt = m.getannotation(mytest.class);
      if(mt!=null){
        //得到注解中的属性
        long out = mt.timeout();
        long start = system.nanotime();
        m.invoke(claz.newinstance(), null);
        long end = system.nanotime();
        if((end-start)>out)
        {
          system.out.println("运行超时");
        }
      }
    }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。如果你想了解更多相关内容请查看下面相关链接

原文链接:https://blog.csdn.net/melissa_heixiu/article/details/52768816