注解

2020-09-10  本文已影响0人  我是许仙

作用**

jdk1.5以后出现的

  1. 编译检查

    @Override 注解 -在编译阶段检查方法是否继承自父类

  2. 编写文档

    javadoc 生成文档

  3. 代码分析 -jdk预定于的注解

    1. @override 检查方法是否继承父类

    ​ <img src="http://ww1.sinaimg.cn/large/006UamUGly1gilobcj5muj30l80ck0th.jpg" alt="image-20200909210239790.png" style="zoom:50%;" />

    <img src="http://ww1.sinaimg.cn/large/006UamUGly1gilobrbk30j30lk0bqjs3.jpg" alt="image-20200909210301542.png" style="zoom:50%;" />

    1. @Deprecate 当前方法已经废弃,但是可以使用
  ```java
   public void  add1() {
          //老的方法,不建议在使用。不能直接删除,需要给程序员提示
      }
  
      public void add2() {
          //新增的方法,希望替代老的方法
      }
  ```

  加入@Deprecate注解

  ```java
  @Deprecated 
  public void  add1() {
      //老的方法,不建议在使用。不能直接删除,需要给程序员提示
  }
  
  public void add2() {
      //新增的方法,希望替代老的方法
  }
  ```

  ![image-20200909210628025.png](https://img.haomeiwen.com/i9388376/d9b281f6e7c12c4a.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 

  可以看到当调用被@Deprecated注解标识的方法的时候,idea工具会提示次方法已经废弃不建议使用,方法中有个-- 。但是方法最终还是可以使用的,只不过给程序员一个提示而已。
  1. @SuppressWarning 压制所有的警告
image-20200909211030827.png
可以看到这段代码中有很多的警告⚠️,但是程序照样可以运行。如果我不想看到这些警告怎么办呢?

在类中添加@SuppressWarning("all")方法。
image-20200909211247520.png

自定义注解

格式

//原注解
public @interface 注解名称 {
  //属性
}
//用@interface

自定义

public @interface Myan {
}

注解的本质

把上面的自定义注解经过javac编译 然后在javap反编译看一下

base) -bash-3.2$ javac Myan.java 
(base) -bash-3.2$ ls
Myan.class  Myan.java
(base) -bash-3.2$ javap Myan.class 
Compiled from "Myan.java"
public interface Myan extends java.lang.annotation.Annotation {
}

可以看到反编译之后是这段代码

public interface Myan extends java.lang.annotation.Annotation {
}

说明注解的本质是一个继承java.lang.annotation.Annotation的接口 ,既然他是接口那么他就会有属性常量和方法

<span style="color:red" >注意,方法的返回值只能是如下类型</span>

  1. 基本类型
  2. string类型
  3. 枚举类型
  4. 注解类型
  5. 以上类型的数组
public @interface Myan {

    //属性常量
    public String name = null;

    //方法
    public String getName();

    public int getAge();

    public ElementType enunType();

    public Myan2 getAn();

    public String[] names();

    public   @interface Myan2 {
    }

}

属性

为什么注解定义的方法通常都叫做属性?

image-20200909214402000.png

​ 当我们使用注解的时候,注解中定义的方法必须都要赋值。

public class Test1 {

    @Myan(getName = "1")
    public String test() {
        return "";
    }
    
}

而给方法赋值的写法特别像在对象中初始化属性。所以通过给注解中定义的方法叫做属性。

多种返回值的属性怎么赋值

public class Test1 {

    @Myan(getName = "1",getAge = 1,getAn = @Myan.Myan2,enunType = ElementType.METHOD,names = {"a","b"})
    public String test() {
        return "";
    }

}

分别给5种属性赋值。数组属性赋值需要{}

default关键字

定义注解使用 default关键字

public   @interface Myan2 {
    String value() default "my";
}
@Myan2
public String test() {
    return "";
}

当属性使用 default关键字初始化属性值的时候, 使用注解可以不设置属性的值。如果不设置使用默认值。

不使用【属性=值】的方式

public   @interface Myan2 {
    String value();
}
@Myan2("1")
public String test() {
    return "";
}

如果注解只有一个属性且属性的名字是value,那么可以直接赋值。不需要使用 key=value的方式

元注解

  1. @Target 表示当前注解可以生效的位置。值是ElementType枚举。常用的有

    1. TYPE可以声明在类上
    2. FIELD可以声明在类的属性中
    3. METHOD可以声明在方法中
    4. PARAMETER 参数
    5. CONSTRUCTOR构造器

    声明一个注解,定义注解只能用在方法上

    @Target(ElementType.METHOD)
    public @interface Myan3 {
    }
    
    image-20200910163804044.png

    如果用在方法上编译报错。

  2. @Retention 描述注解被保留的阶段。

    public enum RetentionPolicy {
        //编译阶段
        SOURCE,
        // 字节码阶段
        CLASS,
        //运行阶段  通常用这个
        RUNTIME
    }
    

    比如说 @SuppressWarnings只在编译阶段有效

    image-20200910164201466.png
  3. @Documented 代表可以生成文档

  4. **@Inherited **描述注解是否可以被子类继承

自定义注解使用案例

自定义一个注解,注解中有2个属性。获取类的全路径 与 获取方法名。通过获取注解中的属性生成一个对象。

定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface InvokeAnno {

    //获取类名
    String getClassName();
    //获取方法名
    String getMethodName();
}

例子

@InvokeAnno(getClassName = "com.javaDemo.annotation.Test3",getMethodName = "log")
public class Test3 {

    public void log() {
        System.out.println("执行方法log----");
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //获取class类
        Class<Test3> test3Class = Test3.class;
        //通过反射获取类中的注解
        InvokeAnno annotation = test3Class.getAnnotation(InvokeAnno.class);
        //获取注解属性
        String className = annotation.getClassName();
        String methodName = annotation.getMethodName();
        //通过反射获取类
        Class<?> aClass = Class.forName(className);
        Object o = aClass.newInstance();
        //通过反射获取方法
        Method method = aClass.getMethod(methodName);
        //调用方法
        method.invoke(o);

    }
}
上一篇 下一篇

猜你喜欢

热点阅读