Java编程思想--20注解

注解(也被称为原数据)为我们在代码中添加信息提供了一种形式化方法,使我们在稍后的某个时刻非常方便地使用这些数据。

Java模前内置了三种标准注解与四种元注解。其中三种标注注解为:

标准注解解释
@Override表示当前类将覆盖超类中的方法。如果拼写错误或者方法签名对应出错,编译器会发出提示。
@Deprecated如果程序员使用了注解为它的元素,编译器会发出警告信息。
@SupressWarnings关闭不当的编译警告信息。

四种元注解如下:

  1. @Target:注解应用的位置
关键字位置
CONSTRUCTORE构造器声明
FIELD域声明
LOCAL_VARIABLE局部变量
METHOD方法声明
PACKAGE包声明
PARAMETER参数声明
TYPE类、接口或enum声明
  1. @Retention:注解的保留级别
关键字含义
SOURCE注解将被编译器丢弃
CLASS注解在class文件中可用,但会被JVM丢弃
RUNTIMEVM在运行时也会保留注解,可以通过反射机制来获取注解信息
  1. @Documented:此注解将包含在Javadoc中。

  2. @Inherited:允许子类继承父类的注解。

20.1 基本语法

  1. 定义注解类
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase{
	public int id;
	public String description() default "no description";
}
  1. 使用注解
//: annotations/PasswordUtils.java
import java.util.*;

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

20.2 编写注解处理器

对于编写的注解,可以利用Java反射机制来编写注解处理器。主要用到两个反射方法:getDeclaredMethods与getAnnotations()。他们都属于AnnotatedElement接口。

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
*///:~

20.2.1 注解元素

可以使用的注解元素主要包括如下类型:

  • 基本类型
  • String
  • Class
  • enum
  • Annotation
  • 以上类型的数组

20.2.2 默认值的限制

元素必须有默认值或者在注解时提供确切的值,无法使用null作为默认值,可以用default关键字设置默认值。

20.2.3 生成外部文件

使用注解可以将所有信息保存在JavaBean源文件中,从而解决与XML文件的同步问题。
例:使用注解定义一个简单的Java Bean

import java.lang.annotation.*;

@Target(ElementType.TYPE) // Applies to classes only
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
  public String name() default "";
} ///:~
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;
} ///:~
@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; }
} ///:~

当某元素是唯一需要赋值的,则无需使用键值对的方式进行一一赋值。

20.5 基于注解的单元测试

可以使用**@Unit注解测试框架进行测试。其中最基本的测试是使用@Test**来标记测试方法。

package annotations;
import net.mindview.atunit.*;
import net.mindview.util.*;

public class AtUnitExample1 {
  public String methodOne() {
    return "This is methodOne";
  }
  public int methodTwo() {
    System.out.println("This is methodTwo");
    return 2;
  }
  @Test boolean methodOneTest() {
    return methodOne().equals("This is methodOne");
  }
  @Test boolean m2() { return methodTwo() == 2; }
  @Test private boolean m3() { return true; }
  // Shows output for failure:
  @Test boolean failureTest() { return false; }
  @Test boolean anotherDisappointment() { return false; }
  public static void main(String[] args) throws Exception {
    OSExecute.command(
      "java net.mindview.atunit.AtUnit AtUnitExample1");
  }
} /* Output:
annotations.AtUnitExample1
  . methodOneTest
  . m2 This is methodTwo
  . m3
  . failureTest (failed)
  . anotherDisappointment (failed)
(5 tests)
>>> 2 FAILURES <<<
  annotations.AtUnitExample1: failureTest
  annotations.AtUnitExample1: anotherDisappointment
*///:~

20.5.4 移除测试代码

使用开源的Javassit工具类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值