java注解

分类:

  源码注解:只在编译器存在 变成 class 文件时不存在

  编译时注解:注解再源码和。class 文件中都存在   Override

  运行时注解:运行阶段还起作用,甚至会影响运行逻辑 AutoWired

 

自定义注解:

  

 

  

 

 

 

 

Inherited 父类有这个注解 子类默认就有

 自定义 java 注解 TestAnnotation:并且为两个属性设置默认值

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    public int id() default -1;
    public String msg() default "hello";

}

Check 注解 自定义 当注解只有一个属性的时候默认属性名为 value

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
String value();
}

没有任何属性的注解 Perform


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Perform {
}

Java 内置的注解:

  @Deprecated:表示一个元素已经过时 例如过时的方法、类、成员变量。

public class Hero {
    @Deprecated
    public void say(){
        System.out.println("hero say method");}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak(){
    System.out.println(</span>"hero speak method"<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    Hero hero </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hero();
    hero.speak();
    hero.say();;
}
</span></span></pre>

  @Override:表示对父类中方法的重写

public class Child extends Father{
    @Override
    public void method() {
        System.out.println("child method");}
}
class Father{
    public void method(){
        System.out.println("fathre method");}
}

  @SuppressWarnings: 阻止警告 被 Deprecated 注解的方法,编译器会警告提示,使用这个注解可以屏蔽掉警告

@SuppressWarnings("deprecation")
public class Hero {
    @Deprecated
    public void say(){
        System.out.println("hero say method");}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak(){
    System.out.println(</span>"hero speak method"<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    Hero hero </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hero();
    hero.speak();
    hero.say();
}

}

  @SafeVarargs: 参数安全类型注解。提醒开发者不要用啊参数做一些不安全的操作,使用该注解会阻止编译器产生 Unchecked 这样的警告

@SafeVarargs // Not actually safe!
    static void m(List<String>... stringLists) {Object[] array = stringLists;
    List<Integer> tmpList = Arrays.asList(42);
    array[0] = tmpList; // Semantically invalid, but compiles without warnings
    String s = stringLists[0].get(0); // Oh no, ClassCastException at runtime!
}

  @FunctionalInterface:java1.8 的新特性 函数式接口 lambda 表达式  例如 Runnable 接口 是一个函数式接口  很容易转换为 lambda

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();}

注解的提取:

注解和反射:

  注解通过反射获取。使用 isAnnotationPresent 方法判断它是否应用了某个注解

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass){}

 通过 getAnnotation 方法获取 Annotation 对象   返回制定类型的注解

public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}

或者是 getAnnotations() 方法  返回注解到这个元素上的所有注解

public Annotation[] getAnnotations() {}

代码示例:

@TestAnnotation
public class Test {
    public static void main(String[] args) {
        boolean hasAnn = Test.class.isAnnotationPresent(TestAnnotation.class);
        if (hasAnn) {
            TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
            System.out.println("id:" + testAnnotation.id());
            System.out.println("msg:" + testAnnotation.msg());}
    }
}

属性和方法上的注解同样可以获取到:通过 java 反射

@TestAnnotation(msg = "qwert")
public class Test {
@Check(</span>"hi"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a;

@Perform
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> test(){}

@SuppressWarnings(</span>"deprecation"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> test1(){
    Hero hero </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hero();
    hero.speak();
    hero.say();
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAnn = Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.isAnnotationPresent(TestAnnotation.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAnn) {
        TestAnnotation testAnnotation </span>= Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.getAnnotation(TestAnnotation.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
        System.out.println(</span>"id:" +<span style="color: rgba(0, 0, 0, 1)"> testAnnotation.id());
        System.out.println(</span>"msg:" +<span style="color: rgba(0, 0, 0, 1)"> testAnnotation.msg());
    }
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{
        Field a </span>= Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredField("a"<span style="color: rgba(0, 0, 0, 1)">);
        a.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取一个成员变量上注解</span>
        Check check = a.getAnnotation(Check.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(check!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
            System.out.println(</span>"check value :"+<span style="color: rgba(0, 0, 0, 1)">check.value());
        }
        Method testMethod </span>= Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredMethod("test"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(testMethod!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
            Annotation[] anns</span>=<span style="color: rgba(0, 0, 0, 1)"> testMethod.getAnnotations();
            </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(Annotation ann : anns){
                System.out.println(ann.annotationType().getSimpleName());
            }
        }

    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchFieldException e) {
        e.printStackTrace();
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchMethodException e) {
        e.printStackTrace();
    }
}

}

 

java 官方文档对注解的解释:

注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
注解有许多用处,主要如下: 
- 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息 
- 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html 文档或者做其它相应处理。 
- 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取

注解不是代码本身的一部分

当开发者使用了 Annotation 修饰了类、方法、Field 等成员之后,这些 Annotation 不会自己生效,必须有开发者提供相应的代码来提取并处理 Annotation 信息。这些提取和处理 Annotation 的代码统称为 APT(Annotation Processing Tool)。

示例:

定义注解 Jiecha

@Retention(RetentionPolicy.RUNTIME)
public @interface Jiecha {
}

 

NoBug.java

public class NoBug {
@Jiecha
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> suanshu(){
    System.out.println(</span>"123456"<span style="color: rgba(0, 0, 0, 1)">);
}

@Jiecha
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> jiafa(){
    System.out.println(</span>"1+1="+1+1<span style="color: rgba(0, 0, 0, 1)">);
}
@Jiecha
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> jianfa(){
    System.out.println(</span>"1-1="+(1-1<span style="color: rgba(0, 0, 0, 1)">));
}

@Jiecha
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> chengfa(){
    System.out.println(</span>"3*5="+(3*5<span style="color: rgba(0, 0, 0, 1)">));
}
@Jiecha
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> chufa(){
    System.out.println(</span>"6/0="+6/0<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> desc(){
    System.out.println(</span>"this is a noBug class desc"<span style="color: rgba(0, 0, 0, 1)">);
}

}

TestTool.java 测试 NoBug 的方法

public class TestTool {
    public static void main(String[] args) {
        NoBug noBug = new NoBug();
        Class clazz = noBug.getClass();
        //反射获取方法
        Method[] methods=clazz.getDeclaredMethods();
        //用来记录测试产生的 log 信息
        StringBuilder log = new StringBuilder();
        //记录异常的次数
        int errorNum =0;
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(Method method : methods){
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(method.isAnnotationPresent(Jiecha.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)){
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                method.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
                method.invoke(noBug,</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span> (IllegalAccessException |<span style="color: rgba(0, 0, 0, 1)"> InvocationTargetException e) {
                errorNum</span>++<span style="color: rgba(0, 0, 0, 1)">;
                log.append(method.getName());
                log.append(</span>" "<span style="color: rgba(0, 0, 0, 1)">);
                log.append(</span>"has error:"<span style="color: rgba(0, 0, 0, 1)">);
                log.append(e.getCause().getClass().getSimpleName());
                log.append(</span>"\n\r"<span style="color: rgba(0, 0, 0, 1)">);
                log.append(e.getCause().getMessage());
                log.append(</span>"\n\r"<span style="color: rgba(0, 0, 0, 1)">);
            }
        }
    }
    log.append(clazz.getSimpleName());
    log.append(</span>" has  "<span style="color: rgba(0, 0, 0, 1)">);
    log.append(errorNum);
    log.append(</span>" error."<span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成测试报告</span>

System.out.println(log.toString());
}
}

结果:

3*5=15
1+1=11
123456
1-1=0
chufa has error:ArithmeticException
/ by zero
NoBug has  1 error.