zoukankan      html  css  js  c++  java
  • 【Java EE 学习 24 上】【注解详解】

    一、注解

      1.所有的注解都是类。

      2.所有的注解都是Annotation接口的子类。

    接口摘要

    Annotation

    所有 annotation 类型都要扩展的公共接口。

      3.定义方式

    public @interface TestAnnotation {
        
    }

      4.可以注解的位置:任何地方都可以,但是要满足注解的具体限制,默认注解可以加在任意位置上

    package com.kdyzm.anotation;
    
    @TestAnnotation
    public class Test {
        @TestAnnotation
        private String name;
        
        @TestAnnotation
        public void show(@TestAnnotation String name)
        {
            @TestAnnotation
            String age;
            System.out.println(name);
        }
    }

      5.使用注解限制注解的位置

      使用@Target注解限制自定义注解的注解位置。

    @Target(value={ElementType.METHOD})//声明只能对方法进行注解,接收数组参数

      具体可以限制的类型:ElementType枚举

    /*
     * %W% %E%
     *
     * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    
    package java.lang.annotation;
    
    /**
     * A program element type.  The constants of this enumerated type
     * provide a simple classification of the declared elements in a
     * Java program.
     *
     * <p>These constants are used with the {@link Target} meta-annotation type
     * to specify where it is legal to use an annotation type.
     *
     * @author  Joshua Bloch
     * @since 1.5
     */
    public enum ElementType {
        /** Class, interface (including annotation type), or enum declaration */
        TYPE,
    
        /** Field declaration (includes enum constants) */
        FIELD,
    
        /** Method declaration */
        METHOD,
    
        /** Parameter declaration */
        PARAMETER,
    
        /** Constructor declaration */
        CONSTRUCTOR,
    
        /** Local variable declaration */
        LOCAL_VARIABLE,
    
        /** Annotation type declaration */
        ANNOTATION_TYPE,
    
        /** Package declaration */
        PACKAGE
    }
    ElementType.java

      6.限制注解在运行时是否删除

      使用@Retention限制注解的存在范围

    @Retention(value=RetentionPolicy.RUNTIME)//声明该注解在运行时保存,即使用方法isAnnotationPresent方法返回值是true

      具体的参数见:RetentionPolicy枚举(保留策略枚举)。

    /*
     * %W% %E%
     *
     * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    
    package java.lang.annotation;
    
    /**
     * Annotation retention policy.  The constants of this enumerated type
     * describe the various policies for retaining annotations.  They are used
     * in conjunction with the {@link Retention} meta-annotation type to specify
     * how long annotations are to be retained.
     *
     * @author  Joshua Bloch
     * @since 1.5
     */
    public enum RetentionPolicy {
        /**
         * Annotations are to be discarded by the compiler.
         */
        SOURCE,
    
        /**
         * Annotations are to be recorded in the class file by the compiler
         * but need not be retained by the VM at run time.  This is the default
         * behavior.
         */
        CLASS,
    
        /**
         * Annotations are to be recorded in the class file by the compiler and
         * retained by the VM at run time, so they may be read reflectively.
         *
         * @see java.lang.reflect.AnnotatedElement
         */
        RUNTIME
    }
    RetentionPolicy.java

      7.注解的作用

        (1)编译时限制作用

    public class MyServlet extends HttpServlet {
        @Override
        public void doGet(ServletRequest req,String name)
                throws ServletException, IOException {
        }
    }

        因为父类没有这个方法,所以加上@Override注解之后就会编译报错。

        (2)运行时反射

        所有类的字节码对象Class、Field、Method、Constructor都拥有一个方法

     该方法用于判断类上、字段上、方法上、构造方法上是否存在注解,如果存在则返回true,否则返回false

     boolean

    isAnnotation()
              如果此 Class 对象表示一个注释类型则返回 true。

        默认自定义注解在运行时删除,但是通过其它注解可以定义该自定义注解的生存范围。怎样定义见6。

      8.注解的实例化

        永远不要实例化注解类,因为注解类是通过系统通过反射实例化的。

      9.给注解定义属性/方法(官方说法为属性)。

        (1)value属性:官方推荐的属性,也是默认的属性,使用方法:public String value();(这种定义方法看上去好像是方法,但是实际上是属性,暂且为属性)

        (2)修饰符必须是public,可以存在static、final修饰,但是不能有其它修饰符。

        (3)默认值:使用关键字default定义,如果没有设置默认值,则在使用注解的时候必须显示赋值才能通过编译。

      10.注解定义示例。

    package com.kdyzm.anotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(value={ElementType.METHOD})//声明只能对方法进行注解,接收数组参数
    @Retention(value=RetentionPolicy.RUNTIME)//声明该注解在运行时保存,即使用方法isAnnotationPresent方法返回值是true
    public @interface MyAnnotation {
        public String value();
        public String name() default "noName";
    }

    二、使用注解小示例。

      1.获取注解的属性值。

      使用Class类、Field类、Method类、Constructor类的getAnnotation方法。  

     

    <A extends Annotation>
    A

    getAnnotation(Class<A> annotationClass)
              如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。

      2.自定义注解小练习。

        (1)自定义注解MyAnnotation

    package com.kdyzm.anotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(value={ElementType.METHOD})//声明只能对方法进行注解,接收数组参数
    @Retention(value=RetentionPolicy.RUNTIME)//声明该注解在运行时保存,即使用方法isAnnotationPresent方法返回值是true
    public @interface MyAnnotation {
        public String value();
        public String name() default "noName";
    }

        (2)在UseMyAnnotation类中使用自定义注解

    package com.kdyzm.setOnMyAnnotation;
    
    import com.kdyzm.anotation.MyAnnotation;
    //使用自定义注解,该注解只能加在方法上。
    public class UseMyAnnotation {
        private String name;
        private int age;
        @MyAnnotation("setName方法")
        public void setName(String name)
        {
            this.name=name;
        }
        @MyAnnotation("getName方法")
        private String getName()
        {
            return name;
        }
        private int getAge()
        {
            return age;
        }
        @MyAnnotation("setAge方法")
        public void setAge(int age)
        {
            this.age=age;
        }
    }

        (3)解析UseMyAnnotation类的所有内容并对注解进行解析。

    package com.kdyzm.demo;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    import com.kdyzm.anotation.MyAnnotation;
    
    //测试自定义注解MyAnnotation的使用,使用MyAnnotation类和UseMyAnnotation类两个类
    public class MyTest {
        public static void main(String[] args) throws Exception {
            String className="com.kdyzm.setOnMyAnnotation.UseMyAnnotation";
            Class cls=Class.forName(className);
            //实例化该类。
            Object obj=cls.newInstance();
            
            //获取该类中的所有方法
            Method []methods=cls.getDeclaredMethods();
            //遍历该方法数组。
            for(Method method:methods)
            {
                boolean flag=method.isAnnotationPresent(MyAnnotation.class);//判断是否进行了方法的注解
                if(flag)//如果进行了方法的注解
                {
                    System.out.print("被注解的方法:");
                    //判断是否是私有的方法
                    if(method.getModifiers()==Modifier.PRIVATE)
                    {
                        //如果是私有的方法则设置暴力破解
                        method.setAccessible(true);
                        System.out.println("该方法私有!方法名为:"+method.getName());
                    }
                    else
                    {
                        System.out.println("该方法共有!方法名为:"+method.getName());
                    }
                    
                    //如果被注解了,输出该注解属性值
                    MyAnnotation annotation=method.getAnnotation(MyAnnotation.class);
                    String value=annotation.value();
                    String name=annotation.name();
                    System.out.println("该注解的内容是:"+value+","+name);
                }
                else//说明是没有被注解的方法
                {
                    System.out.print("没有被注解的方法:");
                    //判断是否是私有的方法
                    if(method.getModifiers()==Modifier.PRIVATE)
                    {
                        //如果是私有的方法则设置暴力破解
                        method.setAccessible(true);
                        System.out.println("该方法私有!方法名为:"+method.getName());
                    }
                    else
                    {
                        System.out.println("该方法共有!方法名为:"+method.getName());
                    }
                }
                System.out.println();
            }
        }
    }

        (4)运行结果。

    没有被注解的方法:该方法私有!方法名为:getAge
    
    被注解的方法:该方法共有!方法名为:setAge
    该注解的内容是:setAge方法,noName
    
    被注解的方法:该方法私有!方法名为:getName
    该注解的内容是:getName方法,noName
    
    被注解的方法:该方法共有!方法名为:setName
    该注解的内容是:setName方法,noName
  • 相关阅读:
    bzoj 3456 城市规划 —— 分治FFT / 多项式求逆 / 指数型生成函数(多项式求ln)
    洛谷 P4721 [模板]分治FFT —— 分治FFT / 多项式求逆
    CF 438 E & bzoj 3625 小朋友和二叉树 —— 多项式开方
    Codeforces 447
    Codeforces 1099
    Codeforces 991
    Codeforces 994
    Codeforces 989
    Codeforces 1084
    xj膜你赛(n-1)
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/4612698.html
Copyright © 2011-2022 走看看