首先了解一下什么是注解: 所谓的注解就是当我们编写代码时,常常见到的@Override、@Deprecated、@SuppressWarnings等,可以查看帮助文档中:java.lang.annotation接口,所有的注解都必须实现该接口。 接下来了解一下注解的作用: 1、 当我们在编写代码时用到一些不建议使用的方法时,就会出现一些黄色的警告,那么这些警告是怎么产生的呢,这就是注解的作用。下面我们通过一个实际的例子来分析一下其情况和过程。 还是先进行了解一下@Deprecated这个注解: @Documented @Retention(value=RUNTIME) public @interface Deprecated用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。 知道了这个注解的作用,那么我们就看一下java.util.Date这个包下的一些方法: @Deprecated public int getSeconds() { return normalize().getSeconds(); } 当注解用在这个方法上时,编译器就知道这个方法是个不建议被使用的方法,当然如果我们用了,那么如果出现意外后果,也只有我们自己承担了。那么我们在编写代码时,如果用到该方法,编译器就会提醒我们不建议我们使用。 2、 了解一下@Override这个注解 表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。 当我们继承父类的某一个方法时,可以在方法的上面添加这个注解,如果不加,也不会有什么影响,但是如果我们加了,但是我们写的方法父类中不存在该方法,则当我们编译的时候,就会报错。 ………… 还有其他的注解作用自己看java帮助文档
接下来,就学习一下如果写自己的注解 注解有两个常用的特征: 1、 注解的生命长度:即这个注解用到什么时候会被编译器抛弃,总共有三个选项,一个注解只能为下列的一种情况。 a) SOURCE:编译器要丢弃的注释。 b) CLASS:编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 c) RUNTIME:编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 2、 注解的使用范围:即注解是在方法上还是类上、抑或是变量上,这类注解的取值可以为多个: a) ANNOTATION_TYPE:注解类型声明 b) CONSTRUCTOR:构造方法声明 c) FIELD:字段声明(包括枚举常量) d) LOCAL_VARIABLE:局部变量声明 e) METHOD:方法声明 f) PACKAGE:包声明 g) PARAMETER:参数声明 h) TYPE:类、接口(包括注释类型)或者枚举声明 那么根据这些情况我们就可以写一些自己的注解:这个示例是圣思园编程竞赛中的一道题 packagedong.application.shengsiyuan; importjava.lang.annotation.ElementType; importjava.lang.annotation.Retention; importjava.lang.annotation.RetentionPolicy; importjava.lang.annotation.Target; //这个注解是用于标示要进行测试的方法 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public@interface Test { } 下面我们使用一下这个注解: packagedong.application.shengsiyuan; publicclass MyClass { public void method1() { System.out.println("method1"); } @Test public void method2() { System.out.println("method2"); } @Test public int add(int a, int b) { return a + b; } @Test public void doSomething(String str) { System.out.println(str); } @Test public void doSomething2() { System.out.println("doSomething2"); } @Test protected void doSomething3() { System.out.println("doSomething3"); } @Test private void doSomething4() { System.out.println("doSomething4"); } @Test void doSomething5() { System.out.println("doSomething5"); } } 下面我们通过反射来获取注解信息,然后根据注解内容进行相应的操作: packagedong.application.shengsiyuan; importjava.lang.reflect.Method; /** * 一个小型框架,用于执行用户的@Test注解的方法 * * @author HS * */ publicclass ApplicationRun { /** * 执行用户@Test注解的方法 *@param className * 要执行的类 *@throws Exception */ public void run(String className) throwsException { // 获取类的Class对象 Class<?> clazz =Class.forName(className); // 获取类中的所有public方法 Method[] methods =clazz.getMethods(); for (Method method : methods) { // 获取每一个方法的@Test注解 Test test =method.getAnnotation(Test.class); // 如果获取的注解不为空则,进行返回值类型判断 if (test != null) { // 如果返回值类型为void,则进行参数个数判断 if(method.getReturnType() == void.class) { // 如果参数个数为0,则执行该方法 if(method.getParameterTypes().length == 0) { method.invoke(clazz.newInstance(),new Object[]{}); } } } } } } 测试类: packagedong.application.shengsiyuan;
publicclass TestMyClass { public static void main(String[] args) { ApplicationRun app = newApplicationRun(); try { app.run("dong.application.shengsiyuan.MyClass"); } catch (Exception e) { e.printStackTrace(); } } } ====================================================================== 这个就是传说中的测试框架的简易模型,注解在以后的框架学习中作用很大,当然如果我们仅仅是框架的使用者、一个机器人,那么没有必要学习框架,只需要按照框架的条条框框去编代码即可。 下面通过反射去获取注解的内容信息: 注解的定义: packagedong.application.annotation; importjava.lang.annotation.Retention; importjava.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public@interface FirstAnnotation { //为注解的参数设置默认值的方法就是在后面加上一个default //当然也可以为数组,其类型也可以根据情况设定 String value() default "lovexiaojing";//李晓静是我的女朋友哦。。。嘻嘻 } 注解的使用: packagedong.application.annotation; @FirstAnnotation("xiaojing") publicclass BaseAnnotationTest { @FirstAnnotation("xiaojing") public String toString() { return "LOVE XIAOJING"; } @FirstAnnotation public String action() { return "FOREVER"; } } 通过反射去获取注解信息: packagedong.application.annotation; importjava.lang.annotation.Annotation; publicclass TestMyAnnotation { @SuppressWarnings("unchecked") public static void main(String[] args) { BaseAnnotationTest bat = newBaseAnnotationTest(); Class<?> clazz =bat.getClass(); FirstAnnotation f =clazz.getAnnotation(FirstAnnotation.class); System.out.println(f.annotationType().isAnnotation()); System.out.println(f.value()); // Annotation[] annotation =clazz.getAnnotations(); // for(Annotation a : annotation) // { // System.out.println(a.annotationType()); // Class<FirstAnnotation>ano = (Class<FirstAnnotation>) a.annotationType(); // System.out.println(ano.getName()); // } } } |
|