zoukankan      html  css  js  c++  java
  • J2SE 8的注解

    1. 注解概念

    (1) 注解格式

    modifiers @interface AnnotationName {
    	type elementName();
    	type elementName() default value;
    }
    

    示例


    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity();
    }

    (2) 概念

    Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。


    元数据

    Java与元数据
    元数据是关于数据的数据。在编程语言上下文中,元数据是添加到程序元素如方法、字段、类和包上的额外信息。
    元数据的作用
      一般来说,元数据可以用于创建文档,跟踪代码中的依赖性,执行编译时检查,代码分析。
    元数据还可用于协助程序元素与框架或者EJB、EMF 和 TestNG这样的工具之间的通信。EJB 3.0就广泛地应用了Java元数据,通过元数据来实现声明性请求企业服务,依赖性以及资源注入,消除了严格的EJB组件模型约束,并且取代了复杂的XML配置文件。
    元数据甚至使我们可以不用修改核心语言,就能够在 Java 语言中添加新功能,使核心语言成为一种开放式语言。在纯面向对象的语言中实现AOP就是使用元数据进行语言扩展的一个很好的例子。AspectWerkz、JBoss AOP以及AspectJ5 使用元数据将类的语义转换为一个aspect、将数据字段转换为一个pointcut、将方法转换为一个advice,等等。
    Java平台的元数据
    Java 元数据(Annotation)是 J2SE 5.0 (研发历时近三年,于2004年9月30日正式发布,代号为“Tiger”)新增加的功能之一,它在JSR-175规范中有详细定义。该机制允许在 Java 代码中添加自定义注释,并允许通过反射(reflection),以编程方式访问元数据注释。通过提供为程序元素附加额外数据的标准方法,元数据功能具有简化和改进许多应用程序开发领域的潜在能力,其中包括配置管理、框架实现和代码生成。

    Annotation不直接影响程序的语义。然而,开发和部署工具可以读取这些注释,并以某种形式处理这些注释,可能生成其他 Java源程序、XML配置文件或者要与包含注释的程序一起使用的其他组件,从而影响运行状态的程序的语义。注释可以从源代码中读取,从编译后的.class文件中读取,也可以通过反射机制在运行时读取。

    Annotation具有以下的一些特点:
    元数据以标签的形式存在于Java代码中。
    元数据描述的信息是类型安全的,即元数据内部的字段都是有明确类型的。
    元数据需要编译器之外的工具额外的处理用来生成其它的程序部件。
    元数据可以只存在于Java源代码级别,也可以存在于编译之后的Class文件内部。
    事实上,早在JDK5.0推出语言级的元数据机制Annotation以前,就一直存在对元数据的需求。但是由于没有提供表达元数据的标准机制,出现了各种解决方案。下面罗列了一些例子
    transient 关键字
    Serializable 标记接口
    xml 部署描述文件
    manifest.mf 文件    
    Javadoc 标记(将文档直接写在源程序里,极大的方便了文档的编写)
    XDoclet(使用类似于JavaDoc的语法撰写描述信息,并使用工具生成描述文件)
    这些方法都存在一定的局限性,比如使用关键字不具有扩展性,用户自定义新的关键字;标记接口没有提供额外的信息,它们不能带有参数,并且只能处理类,而不能处理字段或方法或包。Javadoc和XDoclet标记不会被编译器检查。

    最后,我们再详细的对比一下Annotation和XML部署描述文件的优劣
    XML配置文件与代码文件分离,不利于一致性维护,缺乏在运行时的反射机制。而Annotation与代码一起被编译器处理,并能够在运行时访问。
    通常XML配置文件都很复杂而且冗长,为了配置代码,XML文件必须复制许多信息:比如代码中类名字和方法名字。Java注释则不同,它是代码的一部分,不需要额外的引用就可以指明配置信息。
    XML配置文件是文本文件,没有显式的类型支持,需要到运行时刻才能发现隐藏的错误。而Annotation是类型安全的,它会被编译器检查。  
    XML文件可以表达复杂的关系,但是在注释中我们却很难表达复杂的或层次的结构。
    XML配置文件是在代码之外被单独处理的,也就是说基于XML的配置信息不是硬编码的,可以部署的时候进行修改。而修改Annotation则需要进行重新编译,不过我们可以利用AOP提供的机制为已有的代码添加Annotation。通过部署不同的AOP模块,就能使代码具有不同的Annotation,但比起直接修改XML显得复杂。
    总而言之,注释是简单易用的,并且对大多数应用来说已经足够了。而XML文件更复杂,但具有部署的灵活性,因而被用来处理与部署相关的决策。注释与XML配置文件可以一起使用。由于注释只能保存相当少的配置信息,只有预先集成的框架组件(类似在框架组件中已经完成了大多数预备工作)可以广泛地把注释作为配置选项。而XML配置文件作为一个可选的重载机制,可以用于改变注释的默认行为。


    http://blog.csdn.net/vebasan/article/details/4794699



    • 没带成员变量的Annotation被称为标记,这种注解仅利用自身的存在与否来提供信息,如@Override等。
    • 包含成员变量的Annotation称为元数据Annotation,因为他们提供更多元数据

    (3)使用

    1) 使用注解时,元素的值未指定,就使用默认的default值;

    @AnnotationExample(severity = 1)
    String example;

    2) 均指定

    @AnnotationExample(severity = 1, assignedTo="xyz")
    String example;

    3) type

    注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组

    注解中属性可以有默认值,默认值需要用 default 关键值指定

    (4) 标记注解

    1) 注解中没有任何元素

    public @interface AnnotationExample {
    }
    
    @AnnotationExample
    String example;

    2) 注解中所有元素都使用默认值

    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity() default 0;
    }
    @AnnotationExample
    String example;

    (5) 单值注解

    元素具有特殊名字value(), 没有指定其它元素; 可以忽略这个元素名及等号

    public @interface AnnotationExample {
    	String value();
    }
    @AnnotationExample("the value")
    String example;

    (6) 注解约束

    所有注解的元素值必须是编译期常量;

    一个项可以有多个注解;

    注解可以被重复使用;


    2. 注解this

    ???

    public boolean equals(@AnnotationExample AnnotationTest AnnotationTest.this, @AnnotationExample Object obj) {
        return false;
    }


    3. 元注解

    可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面。
    它的作用和目的就是给其他普通的标签进行解释说明的。

    元标签有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 种.


    @Documented

    给javadoc这样的归档工具提示;被其注解过的方法的归档就会含有这条注解。

    没有加@Documented

    package annotation;
    
    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity();
    }

    package annotation;
    
    public class AnnotationTest {
    	@AnnotationExample(severity = 1, assignedTo = "xyz")
    	public String example;
    	
    	@AnnotationExample(severity = 2)
    	public void foo() {
    		
    	}
    }
    

    加@Documented

    package annotation;
    
    import java.lang.annotation.Documented;
    
    @Documented
    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity();
    }



    package annotation;
    
    public class AnnotationTest {
        @AnnotationExample(severity = 1, assignedTo = "xyz")
        public String example;
        
        @AnnotationExample(severity = 2)
        public void foo() {
            
        }
    }


    @Target

    没有@Target限制的注解可以用于任何项上;


    指定了注解运用的地方(场景)

    元素类型

    注解适用场合

    ElementType.ANNOTATION_TYPE

    注解类型声明

    ElementType.PACKAGE

    ElementType.TYPE

    类型,比如类、接口、枚举

    ElementType.TYPE_PARAMETER
    参数类型

    ElementType.TYPE_USE

    类型用法

    ElementType.FIELD

    属性

    ElementType.CONSTRUCTOR

    构造方法

    ElementType.METHOD

    方法

    ElementType.LOCAL_VARIABLE

    局部变量

    ElementType.PARAMETER

    方法或构造器内的参数

    举例

    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity();
    }
    
    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    @Target({ElementType.FIELD, ElementType.METHOD})
    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity();
    }
    

    java为ElementType枚举增加了TYPE_PARAMETER、TYPE_USE两个枚举值。@Target(TYPE_USE)修饰的注解称为Type Annotation(类型注解),Type Annotation可用在任何用到类型的地方

    package annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface NotNull {
        String value() default "";
    }
    
    package annotation;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class SerializableAnnotation implements @NotNull(value = "Serializable") Serializable {
    	// 泛型中使用Type Annotation 、 抛出异常中使用Type Annotation
    	public void foo(List<@NotNull String> list) throws @NotNull(value = "ClassNotFoundException") ClassNotFoundException {
    		// 创建对象中使用Type Annotation
    		Object obj = new @NotNull String("annotation.Test");
    		
    		// 强制类型转换中使用Type Annotation
    		String str = (@NotNull String) obj;
    	}
    }

    @Retention

    说明了这个注解的的存活时间。


    它的取值如下:
    - RetentionPolicy.SOURCE      注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视,编译器直接丢弃这种Annotation。
    - RetentionPolicy.CLASS         注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。运行java程序时,JVM不可获取Annotation信息。(默认值
    - RetentionPolicy.RUNTIME    注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。 当运行java程序时,JVM也可获取Annotation信息,程序可以通过反射获取该Annotation信息

    举例

    package annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AnnotationExample {
        String assignedTo() default "value";
        int severity();
    }
    


    @Inherited

    Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解

    只能应用于对类的注解,所有的子类自动具有相同的注解。

    举例

    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @interface Test {}
    
    
    @Test
    public class A {}
    
    
    public class B extends A {}
    注解 Test 被 @Inherited 修饰,之后类 A 被 Test 注解,类 B 继承 A,类 B 也拥有 Test 这个注解。


    @Repeatable

    可重复的,注解的值可以同时取多个


    容器注解

    用来存放其它注解的地方,它本身也是一个注解

    里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组,注意它是数组。

    @interface Persons {
        Person[]  value();
    }
    

    属性Person必须被 @Repeatable注解

    @Repeatable(Persons.class)
    @interface Person{
        String role default "";
    }
    

    定义多个角色

    @Person(role="artist")
    @Person(role="coder")
    @Person(role="PM")
    public class SuperMan{
    
    }
    

    4. 预置注解/系统注解

    @Deprecated

    用于表示某个程序元素(类、方法等)已过时。编译时读取,编译器编译到过时元素会给出警告。

    public class Hero {
    
        @Deprecated
        public void say(){
            System.out.println("Noting has to say!");
        }
    
        public void speak(){
            System.out.println("I have a dream!");
        }
    }

    需要注意@Deprecated和@deprecated这两者的区别,前者被javac识别和处理,而后者则是被javadoc工具识别和处理.因此当我们需要在源码标记某个方法已经过时应该使用@Deprecated,如果需要在文档中说明则使用@deprecated.


    @Override

    用来指定方法覆载的,它可以强制一个子类必须覆盖父类的方法。写在子类的方法上,在编译期,编译器检查这个方法,保证父类包含被该方法重写的方法,否则编译出错。该注解只能修饰方法,在编译期被读取。


    @SuppressWarnings

    抑制编译警告/忽视某类编译警告,被该注解修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译警告。

    比如:取消如果程序使用没有泛型限制的集合会引起编译器警告,为了避免这种警告使用该注解。

    关闭编译器对类,方法,成员变量即变量初始化的警告.


    该注解可接受以下参数:

    含义
    deprecated 使用已过时类,方法,变量
    unchecked 执行了未检查的转告时的警告,如使用集合是为使用泛型来制定集合保存时的类型
    fallthrough 使用switch,但是没有break时
    path 类路径,源文件路径等有不存在的路径
    serial 可序列化的类上缺少serialVersionUID定义时的警告
    finally 任何finally字句不能正常完成时的警告
    all 以上所有情况的警告


    unchecked异常:运行时异常。是RuntimeException的子类,不需要在代码中显式地捕获unchecked异常做处理。

    Java异常  http://blog.csdn.net/kingzone_2008/article/details/8535287


    checked和unchecked异常之间的区别是

    Checked异常必须被显式地捕获或者传递,如Basic try-catch-finally Exception Handling一文中所说。而unchecked异常则可以不必捕获或抛出
    Checked异常继承java.lang.Exception类。Unchecked异常继承自java.lang.RuntimeException


    @SafeVarargs

    参数安全类型注解。它的目的是提醒开发者不要用参数做一些不安全的操作,它的存在会阻止编译器产生 unchecked 这样的警告。它是在 Java 1.7 的版本中加入的。


    java7的“堆污染”警告与@SafeVarargs

    堆污染:把一个不带泛型的对象赋给一个带泛型的变量是,就会发生堆污染。


    例如:下面代码引起堆污染,会给出警告

    		List l2 = new ArrayList<Number>();
    		List<String> ls = l2;
    • 3中方式去掉这个警告

      • 使用注解@SafeVarargs修饰引发该警告的方法或构造器。
      • 使用@SuppressWarnings("unchecked") 修饰。
      • 使用编译器参数命令:-Xlint:varargs


    	@SuppressWarnings("unchecked")
    	public void foo() {
    		List l2 = new ArrayList<Number>();
    		List<String> ls = l2;
    	}


    @FunctionalInterface

    函数式接口注解,这个是 Java 1.8 版本引入的新特性。函数式编程很火,所以 Java 8 也及时添加了这个特性。

    使用该注解修饰的接口必须是函数式接口,不然编译会出错。那么什么是函数式接口?

    答:如果接口中只有一个抽象方法(可以包含多个默认default方法或static方法, 还有equals方法),就是函数式接口。


    函数式接口标记有什么用,这个原因是函数式接口可以很容易转换为 Lambda 表达式



    @Generated

    供代码生成工具使用


    @PostConstruct

    控制对象生命周期中,对象被构建后调用


    @PreDestroy

    控制对象生命周期中,对象被移除后调用


    @Resource

    资源注入


    5. 自定义注解

    public @interface 注解名 {
       定义体
    }

    需要注意:

    • 此处只能使用public或者默认的defalt两个权限修饰符
    • 配置参数的类型只能使用基本类型(byte,boolean,char,short,int,long,float,double)和String,Enum,Class,annotation
    • 对于只含有一个配置参数的注解,参数名建议设置中value,即方法名为value
    • 配置参数一旦设置,其参数值必须有确定的值,要不在使用注解的时候指定,要不在定义注解的时候使用default为其设置默认值,对于非基本类型的参数值来说,其不能为null.
    • 以无形参的方法形式来声明Annotation的成员变量,方法名和返回值定义了成员变量名称和类型。使用default关键字设置初始值。没设置初始值的变量则使用时必须提供,有初始值的变量可以设置也可以不设置.


    举例

    package beans.validation.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.validation.Constraint;
    import javax.validation.ConstraintTarget;
    import javax.validation.Payload;
    import javax.validation.constraints.Pattern;
    
    import validation.EmailValidator;
    
    @Pattern.List({
    	@Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+"+"(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"+"@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
    })
    @Constraint(validatedBy={EmailValidator.class})
    @Documented
    @Target({
    	ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER
    })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Email {
    	String message() default "invalid email";
    	Class<?>[] groups() default {};
    	Class<? extends Payload>[] payload() default {};
    	String[] value() default {};
    	
    	//设置约束
    //	ConstraintTarget validationAppliesTo() default ConstraintTarget.PARAMETERS;
    	
    	
    	@Target({
    		ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER
    	})
    	@Retention(RetentionPolicy.RUNTIME)
    	@Documented
    	@interface List{
    		Email[] value();
    	}
    }
    


    6. 注解的提取

    运用反射

    提供了获取Annotation的方法,它的所有实现类也便拥有了这些方法。常见的实现类:

    • Class:类定义。
    • Constructor:构造器定义
    • Field:类的成员变量定义
    • Method:类的方法定义。
    • Package:类的包定义。


    例如, 调用Class对象的方法

        @SuppressWarnings("unchecked")
        public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
            Objects.requireNonNull(annotationClass);
    
            return (A) annotationData().annotations.get(annotationClass);
        }
    
        /**
         * {@inheritDoc}
         * @throws NullPointerException {@inheritDoc}
         * @since 1.5
         */
        @Override
        public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
            return GenericDeclaration.super.isAnnotationPresent(annotationClass);
        }
    
        /**
         * @throws NullPointerException {@inheritDoc}
         * @since 1.8
         */
        @Override
        public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
            Objects.requireNonNull(annotationClass);
    
            AnnotationData annotationData = annotationData();
            return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations,
                                                              this,
                                                              annotationClass);
        }
    
        /**
         * @since 1.5
         */
        public Annotation[] getAnnotations() {
            return AnnotationParser.toArray(annotationData().annotations);
        }
    
        /**
         * @throws NullPointerException {@inheritDoc}
         * @since 1.8
         */
        @Override
        @SuppressWarnings("unchecked")
        public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
            Objects.requireNonNull(annotationClass);
    
            return (A) annotationData().declaredAnnotations.get(annotationClass);
        }
    
        /**
         * @throws NullPointerException {@inheritDoc}
         * @since 1.8
         */
        @Override
        public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
            Objects.requireNonNull(annotationClass);
    
            return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations,
                                                                     annotationClass);
        }
    
        /**
         * @since 1.5
         */
        public Annotation[] getDeclaredAnnotations()  {
            return AnnotationParser.toArray(annotationData().declaredAnnotations);
        } 
    

    调用Field, Method, Constructor的 annotation方法


    7. 注解处理器(Annotation Processor)

    概念

    注解处理器(Annotation Processor)是javac内置的一个用于编译时扫描和处理注解(Annotation)的工具。简单的说,在源代码编译阶段,通过注解处理器,我们可以获取源文件内注解(Annotation)相关内容。

    用途

    由于注解处理器可以在程序编译阶段工作,所以我们可以在编译期间通过注解处理器进行我们需要的操作。比较常用的用法就是在编译期间获取相关注解数据,然后动态生成.java源文件(让机器帮我们写代码),通常是自动产生一些有规律性的重复代码,解决了手工编写重复代码的问题,大大提升编码效率。


    有过Hibernate开发经验的朋友可能知道每写一个Java文件,还必须额外地维护一个Hibernate映射文件(一个名为*.hbm.xml的文件,当然可以有一些工具可以自动生成)下面将使用Annotation来简化这步操作。思路:自定义修饰类的注解,在实体类上使用注解,编写注解处理器:根据源文件中的类上的注解,生成*.hbm.xml文件,使用java提供的编译命令javac执行注解处理器。关键:编写注解处理器。

    我们知道前面的注解处理器处理的都是@Retention(RetentionPolicy.RUNTIME)的注解,使用的是反射技术。而生成的*hbm.xml文件是需要在编译阶段完成。为此java在java7之前提供了apt工具及api,在java7及之后提供了JSR269 api。

    • APT是一种处理注释的工具,它对源代码文件进行检测,并找出源文件中所包含的Annotation信息,然后针对Annotation信息进行额外的处理。
    • APT处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其它的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译生成的源文件和原来的源文件,将它们一起生成class文件.使用APT主要的目的是简化开发者的工作量。
    • 因为APT可以编译程序源代码的同时,生成一些附属文件(比如源文件、类文件、程序发布描述文件等),这些附属文件的内容也都是与源代码相关的,换句话说,使用APT可以代替传统的对代码信息和附属文件的维护工作。
    • APT的相关api都在com.sun.mirror 包下,在jdk7及之后,apt的相关api就被废除了,代替的是JSR269。JSR269API文档下载。JSR269的api在 javax.annotation.processing and javax.lang.model包下。
      所以以后开发注解处理器使用jsr269提供的api就可以了。

    JSR269描述



    ==>

    http://blog.csdn.net/xiang__liu/article/details/79372431



    在 Java8中,已经移除了 APT 工具

    JDK工具-apt命令

    http://www.javacui.com/Theory/367.html

    https://blog.zenfery.cc/archives/78.html




    在编译期获取Java代码文件中的Annotation


    https://www.jianshu.com/p/d7567258ae85

    http://blog.csdn.net/nupt123456789/article/details/51018352

    https://juejin.im/entry/58abebf12f301e006c3c8832

    https://juejin.im/entry/585fe4e61b69e600562147fa

    jar 打包命令详解

    http://blog.csdn.net/marryshi/article/details/50751764




    8. 注解的使用场景


    注解有许多用处,主要如下:
    - 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
    - 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。
    - 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取

    值得注意的是,注解不是代码本身的一部分。
    当开发者使用了Annotation 修饰了类、方法、Field 等成员之后,这些 Annotation 不会自己生效,必须由开发者提供相应的代码来提取并处理 Annotation 信息。这些处理提取和处理 Annotation 的代码统称为 APT(Annotation Processing Tool, item 6)。

    注解什么时候用?取决于你想利用它干什么用。


    比如可以根据反射(item 5) 拿到注解后,针对特定的字段,方法做特定的事情。


    http://blog.csdn.net/J080624/article/details/78269504


    • 生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等
    • 跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都 使用了这种配置来减少配置文件的数量
    • 在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查 出















  • 相关阅读:
    G
    F
    E
    D
    机器学习第二次作业
    机器学习第一次作业
    机器学习作业一
    软工实践个人总结
    第11组 Beta版本演示
    第11组 Beta冲刺(5/5)
  • 原文地址:https://www.cnblogs.com/xiang--liu/p/9710364.html
Copyright © 2011-2022 走看看