Java注解--annotation

本文深入探讨Java注解的概念,包括其定义、使用方法及应用场景。介绍标准注解如@Override、@Deprecated的作用,以及如何利用注解处理器实现元数据驱动的功能。
     注解称为元数据,为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后摸个时刻非常方便的使用这些数据。——Java编程思想第四版.
     注解是众多引入到Java SE5中得语言变化之一。他们可以提供完整的用来描述程序所需的信息,而这些信息是无法使用Java来表达的,注解使得我们可以由编译器来完成测试和验证的格式,存储有关程序的额外信息,属于编译期的类型检查。
     定义注解:其中@Target用来定义你的注解将用在山么地方(例如是一个方法还是一个域)。@Retention用来定义该注解在哪一个级别可以使用(源代码中SOURCE,类文件中CLASS或者运行时RUNTIME)。
import java.lang.annitation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase{
     public int id();
     public String description() default "no description";
}
 
     使用注解:
import java.util.*;

public class PasswordUtils{
     @UseCase(id = 47, description = "")
     public boolean validatePassword(String password){
          return password.matches("\w\w");
     }
     
     @UseCase(id = 48)
     public String encryptPassword(String password){
          return new StringBuilder(password.reverse().toString());
     }
}

元注解:
    @Target(ElementType.[type])
    [type]={METHOD, FIELD, TYPE(类、接口、枚举声明), CONSTRUCTOR, LOCAL_VARIABLE, PARAMETER}
    @Retention(RetentionPolicy.[policy])
    [policy]={SOURCE, CLASS, RUNTIME(反射机制可读取)}
    @Documented 表示将此注解包含到Javadoc中
    @Inherited 表示允许子类继承父类的注解
标准注解:
     注解@Override的代码非常简单,可用于注解类的方法,并在Source级别可用。  并且在Java当中,@Override是可选的
     @Desprecated如果程序员使用了注解为他的元素,那么编译器发出警告信息。
     @SuppressWarnings 关闭不当的编译器警告信息



注解处理器:有了注解是不够的,还需要注解处理器进行注解的处理,否则注解还没有注释好用
import java.lang.reflect.*;
import java.util.*;

public class UseCaseTracker {
public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
     for(Method m : cl.getDeclaredMethods()) {
          UseCase uc = m.getAnnotation(UseCase.class);
          if(uc != null) {
               System.out.println("Found Use Case:" + uc.id() +" " + uc.description());
               useCases.remove(new Integer(uc.id()));
          }
     }
     for(int i : useCases) {
          System.out.println("Warning: Missing use case-" + i);
     }
}

     public static void main(String[] args) {
          List<Integer> useCases = new ArrayList<Integer>();
          Collections.addAll(useCases, 47, 48, 49, 50);
          trackUseCases(useCases, PasswordUtils.class);
     }
}
/* Output:
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
Warning: Missing use case-50
*/

这个程序只用了两个反射的接口:getDeclaredMethods()和getAnnotation(),它们都属于AnnotationElement接口(Class、Method和Field
等类都实现了该接口)getAnnotation()返回指定类型注解对象,然后通过调用id()来返回UseCase对象中提取元素的值。



生成外部文件:
import java.lang.annotation.*;

@Target(ElementType.TYPE) // Applies to classes only
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
     public String name() default "";
}

@DBTable(name = "MEMBER")
public class Member {
     @SQLString(30) String firstName;
     @SQLString(50) String lastName;
     @SQLInteger Integer age;
     @SQLString(value = 30,
          constraints = @Constraints(primaryKey = true))
     String handle;
     static int memberCount;
     public String getHandle() { return handle; }
     public String getFirstName() { return firstName; }
     public String getLastName() { return lastName; }
     public String toString() { return handle; }
     public Integer getAge() { return age; }
}

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
     boolean primaryKey() default false;
     boolean allowNull() default true;
     boolean unique() default false;
}

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
     String name() default "";
     Constraints constraints() default @Constraints;
}

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
     int value() default 0;
     String name() default "";
     Constraints constraints() default @Constraints;
}

public @interface Uniqueness {
Constraints constraints()
     default @Constraints(unique=true);
}

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

public class TableCreator {
  public static void main(String[] args) throws Exception {
    if(args.length < 1) {
      System.out.println("arguments: annotated classes");
      System.exit(0);
    }
    for(String className : args) {
      Class<?> cl = Class.forName(className);
      DBTable dbTable = cl.getAnnotation(DBTable.class);
      if(dbTable == null) {
        System.out.println(
          "No DBTable annotations in class " + className);
        continue;
      }
      String tableName = dbTable.name();
      // If the name is empty, use the Class name:
      if(tableName.length() < 1)
        tableName = cl.getName().toUpperCase();
      List<String> columnDefs = new ArrayList<String>();
      for(Field field : cl.getDeclaredFields()) {
        String columnName = null;
        Annotation[] anns = field.getDeclaredAnnotations();
        if(anns.length < 1)
          continue; // Not a db table column
        if(anns[0] instanceof SQLInteger) {
          SQLInteger sInt = (SQLInteger) anns[0];
          // Use field name if name not specified
          if(sInt.name().length() < 1)
            columnName = field.getName().toUpperCase();
          else
            columnName = sInt.name();
          columnDefs.add(columnName + " INT" +
            getConstraints(sInt.constraints()));
        }
        if(anns[0] instanceof SQLString) {
          SQLString sString = (SQLString) anns[0];
          // Use field name if name not specified.
          if(sString.name().length() < 1)
            columnName = field.getName().toUpperCase();
          else
            columnName = sString.name();
          columnDefs.add(columnName + " VARCHAR(" +
            sString.value() + ")" +
            getConstraints(sString.constraints()));
        }
        StringBuilder createCommand = new StringBuilder(
          "CREATE TABLE " + tableName + "(");
        for(String columnDef : columnDefs)
          createCommand.append("\n    " + columnDef + ",");
        // Remove trailing comma
        String tableCreate = createCommand.substring(
          0, createCommand.length() - 1) + ");";
        System.out.println("Table Creation SQL for " +
          className + " is :\n" + tableCreate);
      }
    }
  }
  private static String getConstraints(Constraints con) {
    String constraints = "";
    if(!con.allowNull())
      constraints += " NOT NULL";
    if(con.primaryKey())
      constraints += " PRIMARY KEY";
    if(con.unique())
      constraints += " UNIQUE";
    return constraints;
  }
} /* Output:
Table Creation SQL for annotations.database.Member is :
CREATE TABLE MEMBER(
    FIRSTNAME VARCHAR(30));
Table Creation SQL for annotations.database.Member is :
CREATE TABLE MEMBER(
    FIRSTNAME VARCHAR(30),
    LASTNAME VARCHAR(50));
Table Creation SQL for annotations.database.Member is :
CREATE TABLE MEMBER(
    FIRSTNAME VARCHAR(30),
    LASTNAME VARCHAR(50),
    AGE INT);
Table Creation SQL for annotations.database.Member is :
CREATE TABLE MEMBER(
    FIRSTNAME VARCHAR(30),
    LASTNAME VARCHAR(50),
    AGE INT,
    HANDLE VARCHAR(30) PRIMARY KEY);
*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值