• java基础解析系列(六)---注解原理及使用


    java基础解析系列(六)---注解原理及使用

    先来一个例子

    class Father
    {
    	public void f()
    	{}
    }
    public class Son extends Father{
    	@Override
    	public void f()
    	{}
    }
    
    
    • 当子类重写父类的方法的时候,上面会出现一个 @Override ,这就是一个注解
    @Controller
    public class StudentController {
    
    
    • 框架中的@Controller也是一个注解

    什么是注解

     public interface Annotation {
         boolean equals(Object obj);
         int hashCode();
         String toString();
         Class<? extends Annotation> annotationType();
    }
    
    
    • 注解是一个接口
    • 从某方面看,注解的作用就像修饰符(public,final,static)一样
    • 程序可以通过反射来获取指定程序元素的Annotion,然后通过Annotion来获取注解里面的元数据。

    注解的种类

    • JDK内置系统注解
    • 元注解,用于'修饰'注解
    • 自定义注解

    JDK内置系统注解

    @Override

    • 上面的例子已经展示,这个注解的作用是用于修饰覆盖了父类的方法

    @Deprecated

    • 这个注解是用来修饰已经过时的方法

    • 可以看到当方法用@Deprecated修饰,然后使用这个方法的时候,编译器会提醒这个方法已经过时

    @SuppressWarnnings

    • 用于忽略编译器警告信息,告诉编译器停止对此方法的警告。

    元注解

    @Target

    • 作用:被描述的注解可以用在什么地方
    • 参数值
    ElementType 含义
    ElementType 含义
    ANNOTATION_TYPE 注解类型声明
    CONSTRUCTOR 构造方法声明
    FIELD 字段声明(包括枚举常量)
    LOCAL_VARIABLE 局部变量声明
    METHOD 方法声明
    PACKAGE 包声明
    PARAMETER 参数声明
    TYPE 类、接口(包括注解类型)或枚举声明
    import java.lang.annotation.Target;
    import java.lang.annotation.ElementType;
    
    
    @Target(ElementType.FIELD)
    public @interface MyAnnotation {
    
    }
    
    
    • 上面是自定义的一个注解,用了一个@Target来修饰,表明这个自定义注解可以用来修饰域

       

    @Retention

    • 作用:指示注释类型的注释要保留多久
    • 参数值
    RetentionPoicy 意义
    SOURCE 源文件中保留,比如@Override,用于与编译器交互
    CLASS source,Class文件保留,用于编译时生成额外的文件
    RUNTIME sorce,class文件,运行时保留

    @Documented

    • 作用:指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化
    • 被@Documented修饰的注解会生成到javadoc中
    import java.lang.annotation.Documented;
    @Documented
    public @interface Demo
    {
    
    }
    
    • 打开cmd,然后执行javadoc Demo.java,然后可以看到这个注解生成到了javadoc

    @Inherited

    • 作用:指示注释类型被自动继承。可以让子类对象使用getAnnotations()获取父类@Inherited修饰的注解。
    
    @Inherited
    @Retention( RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyAnnotation {
    	String msg() default "jiajun";
    }
    
    
    
    @MyAnnotation
    class Father
    {
    
    }
    class son extends Father{
    	
    }
    	
    public class Demo6
    {
    	public static void main(String[] args) {
    		Father f=new son();
    		System.out.println(Arrays.toString(f.getClass().getAnnotations()));
    	}
    }
    //输出:[@MyAnnotation(msg=jiajun)]
    
    

    自定义注解

    格式

    • public @interface 注解名 {定义体}

    @Retention源码

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
        /**
         * Returns the retention policy.
         * @return the retention policy
         */
        RetentionPolicy value();
    }
    
    • 可以看到注解方法返回值是RetentionPolicy枚举类型

    使用

    • 用@interface(区别于interface)来声明一个注解
    • 使用@interface定义注解的时候,自动继承了Annotation接口
    • 用元注解修饰自定义注解
    • 定义体里面可以定义一些参数成员,default设置默认参数值
    • 使用注解的时候,传值方式(msg=""),当参数名是value的时候,可以直接用("666")的形式传值。
    • 当没有传值的时候, @MyAnnotation(),获取到的参数值是默认值

    实验

    @Retention( RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyAnnotation {
    	String msg() default "jiajun";
    }
    
    
    @MyAnnotation(msg="666")
    class Test1
    {}
    public class Test2 {
    	
    	public static void main(String[] args) {
    		Test1 t=new Test1();
    		Class c=t.getClass();
    		MyAnnotation ma = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
    		System.out.println(ma.msg());
    	}
    	
    }
    
    
    • 自定义了一个MyAnnotation注解,用Retention注解声明注解的生命周期,和Target修饰该注解的修饰范围
    • Test1类用自定义的注解修饰,通过Class获取相关信息。当Rention修饰的不是RUNTIME的时候,不能获得相关信息

    访问注解

    访问类注解

    @Retention( RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyAnnotation {
        String name() default "jiajun";
    }
    @MyAnnotation(name="jiajun")
    public class Test {
    }
    public static void main(String[] args) {
            Class clazz = Test.class;
            Annotation[] annotations = clazz.getAnnotations();
            for(Annotation annotation : annotations){
                if(annotation instanceof MyAnnotation){
                    MyAnnotation myAnnotation = (MyAnnotation) annotation;
                    System.out.println("name: " + myAnnotation.name());
                }
            }
    }
    

    访问方法注解

    @Retention( RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MyAnnotation {
        String name() default "jiajun";
    }
    
    public class Test {
        @MyAnnotation(name="jiajun")
        public void doSomething(){}
    }
    
    
    public class Demo {
        public static void main(String[] args) {
            Class clazz=Test.class;
            Method[]  methods=clazz.getMethods();
            for(Method method :methods)
            {
                if(method.getName()=="doSomething")
                {
                    Annotation annotation = method.getAnnotation(MyAnnotation.class);
                    if(annotation instanceof MyAnnotation){
                        MyAnnotation myAnnotation = (MyAnnotation) annotation;
                        System.out.println("name: " + myAnnotation.name());
                    }
                }
            }
        }
    }
    
    

    访问参数注解

    @Retention( RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface MyAnnotation {
        String name() default "jiajun";
    }
    public class Test {
        public static void doSomething(
                @MyAnnotation(name="jiajun") String parameter){
        }
    }
    public class Demo {
        public static void main(String[] args) {
            Class clazz=Test.class;
            Method[]  methods=clazz.getMethods();
            for(Method method :methods)
            {
                if(method.getName()=="doSomething")
                {
                    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                    Class[] parameterTypes = method.getParameterTypes();
    
                    int i=0;
                    for(Annotation[] annotations : parameterAnnotations){
                        Class parameterType = parameterTypes[i++];
    
                        for(Annotation annotation : annotations){
                            if(annotation instanceof MyAnnotation){
                                MyAnnotation myAnnotation = (MyAnnotation) annotation;
                                System.out.println("param: " + parameterType.getName());
                                System.out.println("name : " + myAnnotation.name());
                            }
                        }
                    }
                }
            }
        }
    }
    
    • 每个方法有n个参数,每个参数包含一个注解数组,因此getParameterAnnotations()返回的是一个二维数组

    我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

    作者:jiajun 出处: http://www.cnblogs.com/-new/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。

  • 相关阅读:
    Java反射得到属性的值和设置属性的值
    想建一个比较严格的自律打卡监督群,群主真的会很较真
    JS面向对象篇四、原型链与继承(多种继承实现方式及其利弊分析)
    JS面向对象篇三、创建对象的几种方法
    JS面向对象篇二、什么是原型?原型对象与实例对象、构造函数的关系及相关方法
    JS面向对象篇一、理解对象及属性特性(属性描述符)
    javascript作用域篇一、什么是javascript作用域链
    javascript函数篇四、函数的属性和方法——apply()、call()和bind()方法区别
    javascript函数篇三、函数声明提升
    javascript函数篇二、深入理解为什么javascript中没有函数重载
  • 原文地址:https://www.cnblogs.com/-new/p/7588250.html
Copyright © 2020-2023  润新知