1. 程式人生 > 程式設計 >Java Annotation註解相關原理程式碼總結

Java Annotation註解相關原理程式碼總結

Java.lang 中自帶的註解

  • @Override:表示當前的方法定義將覆蓋基類的方法。如果你不小心拼寫錯誤,或者方法簽名被錯誤拼寫的時候,編譯器就會發出錯誤提示。
  • @Deprecated:如果使用該註解的元素被呼叫,編譯器就會發出警告資訊。
  • @SuppressWarnings:關閉不當的編譯器警告資訊。
  • @SafeVarargs:在 Java 7 中加入用於禁止對具有泛型varargs引數的方法或建構函式的呼叫方發出警告。
  • @FunctionalInterface:Java 8 中加入用於表示型別宣告為函式式介面

如何定義註解

以下是一個為標記註解(marker annotation),不包含任何元素

package cn.haidnor.annotation;

import java.lang.annotation.*;

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

註解的定義也需要一些元註解(meta-annoation),比如 @Target 和 @Retention。

@Target 定義你的註解可以應用在哪裡(例如是方法還是欄位)。

@Retention 定義了註解在哪裡可用,在原始碼中(SOURCE),class檔案(CLASS)中或者是在執行時(RUNTIME)。

Demo 簡單例項

定義註解

以下的程式碼中。Target 定義只能在方法上使用,Retention 定義保留域

package cn.haidnor.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
  int id();
  String description() default "no description";
}

在類中使用註解

package cn.haidnor.clazz;
package cn.haidnor.clazz;
import cn.haidnor.annotation.UseCase;
import java.util.List;

public class PasswordUtils {
  @UseCase(id = 47,description ="Passwords must contain at least one numeric")
  public boolean validatePassword(String passwd) {
    return (passwd.matches("\\w*\\d\\w*"));
  }
  @UseCase(id = 48)
  public String encryptPassword(String passwd) {
    return new StringBuilder(passwd)
        .reverse().toString();
  }
  @UseCase(id = 49,description = "New passwords can't equal previously used ones")
  public boolean checkForNewPassword(
      List<String> prevPasswords,String passwd) {
    return !prevPasswords.contains(passwd);
  }
}

對以上 demo 中的程式碼進行測試

package cn.haidnor.test;

import cn.haidnor.annotation.UseCase;
import cn.haidnor.clazz.PasswordUtils;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.*;
import java.lang.reflect.*;

public class UseCaseTracker {

  public static void main(String[] args) {
    List<Integer> useCases = IntStream.range(44,51)
        .boxed().collect(Collectors.toList());
    trackUseCases(useCases,PasswordUtils.class);
  }

  public static void trackUseCases(List<Integer> useCasesList,Class<?> clazz) {
    // getDeclaredMethods() 獲取所有公開的方法
    for(Method m : clazz.getDeclaredMethods()) {
      // getAnnotation() 獲取指定註解
      UseCase uc = m.getAnnotation(UseCase.class);
      if(uc != null) {
        System.out.print("Found Use Case ");
        // 提取註解元素值
        System.out.println(uc.id());
        // 提取註解元素值
        System.out.println('\t' + uc.description());
        useCasesList.remove( Integer.valueOf( uc.id() ) );
      }
    }

    // 迭代集合
    useCasesList.forEach(new Consumer<Integer>() {
      @Override
      public void accept(Integer integer) {
        System.out.println("Missing use case " + integer);
      }
    });
    // 以上程式碼可以使用箭頭行數簡寫
    // useCasesList.forEach(i -> System.out.println("Missing use case " + i));
  }
}

控制檯輸出結果

Found Use Case 47
  Passwords must contain at least one numeric
Found Use Case 48
  no description
Found Use Case 49
  New passwords can't equal previously used ones
Missing use case 44
Missing use case 45
Missing use case 46
Missing use case 50

元註解

Java 語言中目前有 5 種標準註解(前面介紹過),以及 5 種元註解。元註解用於註解其他的註解

Java Annotation註解相關原理程式碼總結

註解中可以使用的元素

所有基本型別(int、float、boolean等)

  • String
  • Class
  • enum
  • Annotation
  • 以上型別的陣列

其他型別,編譯器就會報錯。注意,也不允許使用任何包裝型別

  • 註解的預設值

無論是在原始碼宣告時還是在註解介面中定義預設值時,都不能使用 null 作為其值。

import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimulatingNull {
  int id() default -1;
  String description() default "";
}

使用反射獲取註解的方法流程圖

Java Annotation註解相關原理程式碼總結

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。