`

Java注解

 
阅读更多

Java注解是在JDK1.5引入的,以@注解名存在代码中。

声明一个注解使用@interface,其中每个方法实际上是声明了一个配置参数,方法名即参数名,返回类型即参数类型。

通过default来设置默认值。

@Retention@Target用来声明注解的本身的行为。@Retention指明注解保留策略,有RetentionPolicy.SOURCE(源码)、RetentionPolicy.RUNTIMEJVM运行时)、RetentionPolicy.CLASS(类文件)3种。只有当声明为RUNTIME时才可以通过java的反射API来获取注解信息。

@Target指明了注解作用的类型,有包、类、方法、构造方法、字段、本地变量、方法参数等。所有的注解都是自动继承Annotation的。

 

包类型的注解

定义一个包类型的注解:

package com.ant.test.annotation;

 

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-19 下午2:33:50

 */

 

@Target(ElementType.PACKAGE)

@Retention(RetentionPolicy.RUNTIME)

public@interfacePkgAnnotation {

    String description();

}

 

然后再某个类的Package声明上加上这个注解

 

加了之后,编译器立马显示错误,如上图。具体提示信息如下:

Package annotations must be in file package-info.java.

这个错误信息相当明显,即包类型的注解需要在package-info.java文件中。

 

Ok,好吧,创建一个package-info.java文件,用Eclipse创建发现是没法创建的,提示Type name is not valid. The type name 'package-info' is not a valid identifier。得,咱用记事本创建,Ok,创建了一个package-info.java:

@PkgAnnotation

package com.ant.test.annotation;

Ok ,我们在com.ant.tets.annotation包上应用注解。这次编译没有报错。

在上面,这个包类型的注解我们指定了是RetentionPolicy.RUNTIME,因此,可以通过Java的发射API获取包com.ant.test.annotation上的所有注解。

 

package com.ant.test.annotation;

 

import java.lang.annotation.Annotation;

 

import org.apache.log4j.Logger;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-19 下午1:55:14

 * @version V1.0

 */

publicclass Bean {

    private Logger logger = Logger.getLogger(Bean.class);

   

    publicvoid testPkgAnnotation1() {

        logger.info("测试包类型的注解。。。");

        String pkgName = "com.ant.test.annotation";

        Package pkg = Package.getPackage(pkgName);

        Annotation[] annotations = pkg.getAnnotations();

        for (Annotation annotation:annotations) {

            if (annotation instanceofPkgAnnotation) {

                logger.info("This is PkgAnnotation.");

                logger.info("package description:" + ((PkgAnnotation)annotation).description());

            }

        }

    }

   

    publicstaticvoid main(String[] args) {

        Bean b = new Bean();

        b.testPkgAnnotation1();

    }

}

 

输出:

[08/19 16:59:50] [INFO] Bean: 测试包类型的注解。。。

[08/19 16:59:50] [INFO] Bean: This is PkgAnnotation.

[08/19 16:59:50] [INFO] Bean: package description:This is the test msg for this pacakge.

 

TIP:package-info.java是一个比较特殊的文件,平时没人会关注到它。在Spring的源文件中,我们可以看到package-info.java的影子,它就是用来描述一个包的。其次,就是上面所看到的,为标注在包上的注解提供便利。在package-info.java中还可以创建具有包级访问权限的类和常量,当然,类名也不可能是public的,否则你的文件名就得是类名了。

 

如下,在package-info中加了2个类,一个Test,一个PkgConstants

@PkgAnnotation(description = "This is the test msg for this pacakge.")

package com.ant.test.annotation;

 

class Test {

    publicvoid test() {

        System.out.println("This is a test method in package.");

    }

       

}

 

class PkgConstants {

    publicstatic String PACKAGE_NAME = com.ant.test.annotation.PkgConstants.class.getPackage().getName();

}

2个类都是在同一个包下的类可以访问的。

 

Bean.java中另加一个方法来测试:

publicvoid testPkgAnnotation2() {

        logger.debug("测试package-info.java中的类和常量。");

       

        Test  test = new Test();

        test.test();

       

        String packageName = PkgConstants.PACKAGE_NAME;

        logger.info("packagename:" + packageName);

    }

运行,程序输出:

       08/19 17:14:53] [DEBUG] Bean: 测试package-info.java中的类和常量。

This is a test method in package.

[08/19 17:14:53] [INFO] Bean: packagename:com.ant.test.annotation

 

1.     方法上的注解

下面定义一个作用于方法上的注解:

package com.ant.test.annotation;

 

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-19 下午1:54:08

 */

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public@interfaceMyAnno {

    int value() default 0;

    String name();

    Color color() default Color.BLUE;

    String[] className() default {};

    enum Color{RED,BLUE,GREEN};

}

 

如上,int value() default 0这里,如果在注解中指定了value(),如果没有其他的方法,那么在使用注解的时候,你可以直接用注解的名字就行了,如@MyAnno

 

注解中指定了默认值的参数则在使用时不指定值的情况下会使用默认值。

下面是测试方法:

@MyAnno(name = "abc")

    publicvoid testMyAnno1() {

        logger.info("测试自定义注解。。。");

       

        Method method = null;

        try {

            method = Bean.class.getMethod("testMyAnno1", null);

        } catch (SecurityException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        } catch (NoSuchMethodException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

       

        MyAnno ma = method.getAnnotation(MyAnno.class);

        logger.info("value:" + ma.value());

        logger.info("name:" + ma.name());

        logger.info("color:" + ma.color());

        logger.info("className:" + (ma.className().length == 0 ? "{}":ma.className()));

    }

因为注解中只有name没有指定默认值,因此这里只需要对name指定值。

输出:

[08/20 09:23:37] [INFO] Bean: 测试自定义注解。。。

[08/20 09:23:38] [INFO] Bean: value:0

[08/20 09:23:38] [INFO] Bean: name:abc

[08/20 09:23:38] [INFO] Bean: color:BLUE

[08/20 09:23:38] [INFO] Bean: className:{}    

从输出我们可以看到,除了name外其他的都是使用的默认值。

2.     类上的注解

定义一个作用于类上的注解:

package com.ant.test.annotation;

 

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-20 上午9:26:20

 */

 

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public@interfaceClassAnnotation {

    String url();

    RequestMethod method() default RequestMethod.POST;

    enum RequestMethod {

        GET,POST

    }

}

 

测试类:

package com.ant.test.annotation;

 

import org.apache.log4j.Logger;

 

import com.ant.test.annotation.ClassAnnotation.RequestMethod;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-20 上午9:28:21

 */

 

@ClassAnnotation(url="/jsp/index.htm",method=RequestMethod.POST)

publicclass TestClassAnnotation {

    privatestatic Logger logger = Logger.getLogger(TestClassAnnotation.class);

   

    publicstaticvoid main(String[] args) {

        logger.info("Test Annotation Effect On Class.");

       

        ClassAnnotation ca = TestClassAnnotation.class.getAnnotation(ClassAnnotation.class);

        logger.info("url:" + ca.url());

        logger.info("method:" + ca.method().name());

    }

}

 

 

输出:

[08/20 09:46:00] [INFO] TestClassAnnotation: Test Annotation Effect On Class.

[08/20 09:46:00] [INFO] TestClassAnnotation: url:/jsp/index.htm

[08/20 09:46:00] [INFO] TestClassAnnotation: method:POST

 

3.     注解的继承

注解是可以继承的,当然必须在注解上指定@Inherited

还是那#3中的例子:

首先,在注解上加上@Inherited,表示可以被继承。

package com.ant.test.annotation;

 

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-20 上午9:26:20

 */

 

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Inherited

public@interfaceClassAnnotation {

    String url();

    RequestMethod method() default RequestMethod.POST;

    enum RequestMethod {

        GET,POST

    }

}

然后,定义一个类,在类上使用注解。

package com.ant.test.annotation;

 

import com.ant.test.annotation.ClassAnnotation.RequestMethod;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-20 上午9:52:30

 * @version V1.0

 */

 

@ClassAnnotation(url="/jsp/index.do",method=RequestMethod.POST)

publicclass ClassAnno {

 

}

最后定义一个子类继承ClassAnno

package com.ant.test.annotation;

 

import java.lang.annotation.Annotation;

 

/**

 * @Description: TODO

 * @author luckystar2008

 * @date 2013-8-20 上午9:51:44

 */

 

publicclass InheritClass extends ClassAnno {

    publicstaticvoid main(String[] args) {

        Annotation[] anns = InheritClass.class.getAnnotations();

        for (Annotation ann:anns) {

            System.out.println(ann);

        }

    }

}

 

输出:

@com.ant.test.annotation.ClassAnnotation(method=POST, url=/jsp/index.do)

 

如果你不在注解上加@Inherited,那么这里也不会有任何输出了。

 

当然,注解还可以作用与字段、构造方法、变量、方法参数等上面。

SpringMVC中就使用了作用于类上的@Controller,作用于方法上的@RequestMapping,作用于方法参数的@ModelAttribute等。

通过指定注解的@Retention(RetentionPolicy.RUNTIME),通过反射API获取到注解的值,这样就可以改变对象的行为。通过在方法上使用权限注解,达到细粒度的控制权限等。

 

相对于XML配置和注解配置,我个人更喜欢注解.

分享到:
评论

相关推荐

    java注解代码java注解代码

    java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解...

    Eclipse Java注释模板.txt

    ### Eclipse Java注释模板知识点详解 #### 一、概述 在进行Java开发的过程中,良好的代码注释习惯不仅能帮助自己快速回顾代码逻辑,还能方便其他开发者理解代码意图,从而提高整个团队的工作效率。Eclipse作为一款...

    java注解webservice学习第一篇

    Java注解是Java编程语言中的一个重要特性,它允许在代码中添加元数据,为编译器、解释器或任何其他工具提供额外的信息。在Java Web服务(WebService)开发中,注解的应用极大地简化了服务的创建和配置。本文将深入...

    java注解大全(非常全面)

    Java注解是Java编程语言中的一个重要特性,它们提供了一种元数据的方式,允许程序员在代码中插入信息,这些信息可以被编译器或运行时环境用于处理代码。注解不仅简化了开发,还增强了代码的可读性和维护性。本资料...

    Java注释全解文档

    除了上述框架特定的注解,还有一些通用的Java注解,如@Override表明方法重写父类方法,@Deprecated标记已废弃的方法,@ SuppressWarnings抑制编译器警告。理解并熟练运用这些注解,能够提升代码质量,减少出错可能性...

    Java注解实现方式

    Java注解是Java编程语言中的一个重要特性,它允许程序员在代码中嵌入元数据,这些元数据可以被编译器或运行时环境用来执行各种任务,例如代码分析、验证、生成代码、部署等。注解提供了更加灵活和可扩展的方式来处理...

    java注解深入理解

    Java注解是Java编程语言中的一个重要特性,它提供了一种元数据的方式,允许程序员在代码中插入额外的信息,这些信息可以被编译器或者运行时环境用来执行特定的任务。注解在现代Java开发中扮演了不可或缺的角色,尤其...

    java注解和反射的个人学习笔记

    java注解和反射的个人学习笔记

    Java注释模板使用

    本文将深入探讨Java注释的类型、用途,以及如何创建和使用注释模板,以帮助您和您的团队提升代码质量。 1. **Java注释类型**: - **单行注释**:以`//`开头,常用于快速添加临时性的注释或简单的解释。 - **多行...

    java 注解开发(包含详细注释,项目可以直接运行)

    Java注解是自JDK1.5版本引入的一种元数据机制,它允许程序员在源代码的各个层次(类、方法、变量等)嵌入信息,这些信息可以被编译器或者运行时系统用来进行各种处理。注解简化了配置文件的使用,提高了代码的可读性...

    java 注解

    Java注解是Java编程语言中的一个重要特性,它允许程序员在代码中嵌入元数据(metadata),这些元数据不直接影响程序的执行,但可以被编译器或运行时环境用来进行各种处理,如验证、动态代理、持久化、资源管理等。...

    JAVA 注解示例 详解

    本篇文章将深入探讨Java注解的使用及其在实际开发中的应用。 首先,我们了解Java注解的基本结构。一个注解以`@`符号开头,后面跟着注解类型,如`@Override`或`@Deprecated`。注解可以带有参数,参数以键值对的形式...

    java注解解析知识要点

    完整注释可以包含多个参数,但 Java 内置的注解通常只使用上述两种形式。 元数据的作用主要体现在三个方面: - **编写文档**: 通过如 Javadoc 一样的工具,可以从注解中提取信息来生成代码的文档,提高代码的...

    入门级java 注解学习示例代码

    Java注解(Annotation)是Java语言的一个重要特性,它为元数据提供了强大的支持。元数据是一种描述数据的数据,它提供了一种安全的方式,使我们可以在不改变程序代码本身的情况下,向编译器或运行时环境提供额外的...

    Java注解的使用例子

    Java注解(Annotation)是Java语言的一个重要特性,它为元数据提供了一种结构化的方式。元数据是在程序代码中包含的关于程序本身的信息,但这些信息并不直接影响程序的执行。注解允许开发者向编译器、JVM或工具提供...

    java注解_反射_字节码_类加载机制.zip

    Java注解、反射、字节码和类加载机制是Java编程中的核心概念,它们在实际开发中扮演着重要角色。让我们深入探讨这些知识点。 **Java注解(Annotation)**: Java注解是一种元数据,它提供了在编译时或运行时处理代码的...

    java 注释模板 超级好用

    超级好用的 java 注释模板,吐血总结,整理。吐血总结,整理。

    spring4基于java注解事例

    在本教程中,我们将深入探讨如何使用Spring 4框架,特别是其基于Java注解的配置方式,来构建一个高效、可维护的系统。Spring 4是Java企业级应用开发的首选框架,它提供了广泛的功能,包括依赖注入、AOP(面向切面...

    Eclipse Java 注释模板

    Eclipse作为一款强大的Java集成开发环境(IDE),提供了许多便捷的功能,其中之一就是“Eclipse Java 注释模板”。通过配置和使用这些模板,程序员可以快速地为代码添加注释,提高代码的可读性和维护性。下面我们将...

Global site tag (gtag.js) - Google Analytics