JDK 5.0 注解的使用

了解注解

  在编写代码时,除了源程序以外,我们还会使用Javadoc标签对类、方法或成员变量进行注解,一遍使用Javadoc工具生成和源代码配套的Javadoc文档。

/**
* 重写toString
* @param id
* @param name
* @return
*/
public String toString(int id, String name) {
    return id+","+name;
}

  这些@param、@return等javadoc标签就是注解标签,它们为第三方工具提供了描述程序代码的注释信息。

  JDK 5.0注解可以看成是Javadoc标签和Xdoclet标签的延伸和发展。在JDK 5.0中,我们可以自定义这些标签,并通过Java语言的反射机制获取类中标注的注解,完成特定的功能。

  注意,注解是代码的附属信息,就像你对一本好书进行的批注,书的内容并没有因为注解而影响阅读或改变,所以注解遵循一个基本原则:注解不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。Java语言解释器会忽略这些注解,而由第三方工具负责对注解进行处理。第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过Java反射机制读取注解的信息,并根据这些信息更改目标程序的逻辑,而这正是SpringAOP对@AspectJ提供支持所采取的方法。

一个简单的注解类

  定义注解类本身并不困难,Java提供了定义注解的语法。下面来编写一个栗子??:

package com.zhengbin.annotationtest.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Created by zhengbin06 on 2016/10/15.
 */
@Retention(RetentionPolicy.RUNTIME) //①声明注解的保留期限
@Target(ElementType.METHOD) //②声明可以使用该注解的目标类型(这里表明该注解的目标类型是方法,查看@Target的实现,可以看到它的成员为ElementType类型的数组)
public @interface NeedTest { //③定义注解
    boolean internal() default true; //④声明注解成员
    // 注解成员的类型、成员名、与默认值
}

  Java新语法规定使用@interface修饰符定义注解类,如③所示,一个注解类可以有多个成员,成员声明和接口方法声明类似,这里只定义了一个成员,如④所示。成员的声明有一下几点限制:

  • 成员以无入参无抛出异常的方式声明,比如boolean value(String str)、boolean value() throws Exception等方式都是非法的;
  • 可以通过default为成员制定一个默认值,如String level default "LOW_LEVEL"、int hight() default 2都是合法的。当然也可以不制定默认值;
  • 成员类型是受限的,合法的类型包括原始类型及其分装类、String、Class、enums、注解类型,以及上述类型的数组类型。如List foo() 就是非法的。

  成员也可以是注解类型,下面就修改一下NeedTest.java:

  • 添加一个Student.java:
package com.zhengbin.annotationtest.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Created by zhengbin06 on 2016/10/15.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Student {
    String id() default "201370034217";
    String name() default "郑斌";
    int age() default 21;
}
  • 修改NeedTest.java:
@Retention(RetentionPolicy.RUNTIME) //①声明注解的保留期限
@Target(ElementType.METHOD) //②声明可以使用该注解的目标类型(这里表明该注解的目标类型是方法,查看@Target的实现,可以看到它的成员为ElementType类型的数组)
public @interface NeedTest { //③定义注解
    boolean internal() default true; //④声明注解成员
    // 注解成员的类型、成员名、与默认值
    Student student();
}

  在①和②处,我们所看到的注解是Java预定义的注解,成为元注解(Meta-Annotation),它们被Java编译器使用,会对注解类的行为产生印象。@Retention(RetentionPolicy.RUNTIME)表示NeedTest这个注解可以在运行期被JVM读取,注解的保留期限类型在java.lang.annotation.Retention类中定义,介绍如下:

  Target(ElementType.METHOD)表示NeedTest这个注解只能应用到目标类的方法上,注解的应用目标在java.lang.annotation.ElementType类中定义:

  所有的注解类都隐式继承于java.lang.annotation.Annotation,但注解不允许显式继承于其他的接口。

使用注解

  下面我们在ManageService.java中使用注解:

package com.zhengbin.annotationtest.service;
import com.zhengbin.annotationtest.anno.NeedTest;
import com.zhengbin.annotationtest.anno.Student;
/**
 * Created by zhengbin06 on 2016/10/15.
 */
public class ManageService {
    @NeedTest(student = @Student)// ①
    public void accessStudent() {
        System.out.println("中工来了个小学弟!");
    }
    @NeedTest(internal = false, student = @Student(name = "郑斌" , age = 21))// ②
    public void graduateStudent() {
        System.out.println("曾经的小学弟要毕业了。。。");
    }
}
  • 在①处,因为@NeedTest注解类的internal成员有默认值,所以在这里可以不用再进行赋值,但是student成员是一个注解类,所以必须申明出来,但同时也不必赋值,这样使用的就是声明的默认值
  • 在②处,这是完整的声明和赋值

访问注解

  前面提到过,注解不会直接影响程序的运行,但是第三方程序或工具可以利用代码中的注解完成特殊的任务,间接控制程序的运行。对于RetentionPolicy.RUNTIME保留期限的注解,我们可以通过反射机制访问类中的注解。

  在JDK 5.0里,Package、Class、Constructor、Method以及Field等反射对象都新增了访问注解信息的方法:

<T extends Annotation>T getAnnotation(Class<T> annotationClass)

  下面,我们就通过反射来访问注解,得出ManageService类中通过@NeedTest注解所承载的测试需求,如下:

package com.zhengbin.annotationtest.test;
import com.zhengbin.annotationtest.anno.NeedTest;
import com.zhengbin.annotationtest.service.ManageService;
import java.lang.reflect.Method;
/**
 * Created by zhengbin06 on 2016/10/15.
 */
public class TestTool {
    public static void main(String[] args) {
        Class clazz = ManageService.class;
        Method[] methods = clazz.getMethods();
        System.out.println(methods.length);
        for (Method method : methods) {
            NeedTest needTest = method.getAnnotation(NeedTest.class);
            if (needTest != null) {
                if (needTest.internal()) { // ①
                    System.out.println("小学弟:"+needTest.student().name()); // ②
                }else {
                    System.out.println("毕业僧:"+needTest.student().name());
                }
            }
        }
    }
}
  • 在①处,判断成员internal的值
  • 在②处,获得成员student在ManageService中的注解信息

  运行以上的代码,输出以下的信息:

11
小学弟:郑斌
毕业僧:郑斌

  方法个数为11,除了我们申明的两个,其它都是父类Object的方法。

时间: 2024-12-08 22:08:03

JDK 5.0 注解的使用的相关文章

[javaSE] 注解-JDK中的注解

java中的常见注解 jdk自带注解:@Override 覆盖  @Deprecated 过期  @Suppvisewarnings 压制警告 package com.tsh.ano; public class AnoDemo { public static void main(String[] args) { Person person=new Student(); person.getName(); //下面会有一个删除线 person.sing(); } } interface Perso

安装Oracle JDK 7.0与8.0 for Mac OS X后Eclipse启动报错的解决之道

启动 Eclipse 时,直接报错The JVM shared library "/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/bin/../jre/lib/server/libjvm.dylib"does not contain the JNI_CreateJavaVM symbol. Unable to find any JVMs matching architecture "i386&qu

6.28笔记-servlet3.0注解配置、文件上传、过滤器、监听器

一.servlet3.0注解配置 使用javaEE6.0 支持servlet3.0 value的值就是访问路径 urlPatterns的值也是访问路径 @WebServlet(name="DemoServlet3",value="/demoServlet3") public class DemoServlet3 extends HttpServlet { ... } 二.文件上传 表单 method 必须是post enctype="multipart/f

spring 4.0 注解数据验证2

在spring 4.0 注解数据验证1中有基本的数据验证方法.还是那个POJO: package com.suyin.pojo; import java.lang.reflect.Field; import org.hibernate.validator.constraints.NotBlank; public class People { private int id; @NotBlank private String name; private String address; private

Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制--转载

多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之一就是,它是第一个直接把跨平台线程模型和正规的内存模型集成到语言中的主流语言.核心类库包含一个 Thread 类,可以用它来构建.启动和操纵线程,Java 语言包括了跨线程传达并发性约束的构造 ——synchronized 和 volatile .在简化与平台无关的并发类的开发的同时,它决没有使并发类的编写工作变得更繁琐,只是使它变得更容易了. synchronized 快速回顾 把代码块声明为 synchronized,有两个重

运用servlet3.0注解报404错误

我的环境是eclipse (查了一下2013EEIDE)+tomcat7.0+Servlet3.0 项目名称:day08BookManageCase servlet类是new servlet出来的如下代码,大部分代码省略,只留了注解部分. /** * Servlet implementation class FindAllServlet */ @WebServlet("/FindAllServlet") public class FindAllServlet extends HttpS

AndroidStudio3.0 注解报错Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor.

体验最新版AndroidStudio3.0 Canary 8的时候,发现之前项目的butter knife报错,用到注解的应该都会报错 Error:Execution failed for task ':app:javaPreCompileDebug'. > Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to

Servlet3.0注解为什么不能使用?及配置多个Tomcat

在学校学习Servlet和过滤器的时候,通常是在web.xml文件中配置的,这样可以将配置信息集中在一起,方便修改,而且如果采用注解的形式,会在编译的过程中将注解一同编译进去,这样就无法方便的进行修改了,如果是远程操作的话,就造成了很大的麻烦. 一,使用注解应当注意的事项: 开发Servlet3.0的程序需要环境支持: IDE:MyEclipse 10+ JDK:JDK 1.6+ tomcat:tomcat 7+ 当你的环境正确的时候才能正常使用,尤其需要注意的是,MyEclipse自带的Tom

Servlet3.0注解新特性笔记 (转载IBM)

Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署.其中有几项特性的引入让开发者感到非常兴奋,同时也获得了 Java 社区的一片赞誉之声: 异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程.在接收到请求之后,Servlet 线