您的位置:首页 > 编程语言 > Java开发

Java 注解简单学习

2017-08-21 09:16 344 查看

1、注解的概述:

 

注解是用来替代配置文件的!你回忆一下,我们以前总是要写一些配置文件,例如web.xml你还记得么?里面要写<servlet>和<servlet-mapping>!谁来读配置文件呢?当然是Tomcat!谁来写配置文件呢?当然是我们来写了!

在Servlet3.0中就可以使用使用注解来代替配置文件,开发者就不用再写配置文件了,而是写注解,然后Tomcat来读取注解。注解也是类,需要定义了才能使用!分别在Servlet3.0中有一个注解类为@WebServlet,然后我们就可以在Servlet中使用

@WebServlet中使用这个注解了。这个注解就是用来替代<servlet>了。然后Tomcat会通过反射来读取注解中的信息!

小结:

  注解的语法:@注解名称

  注解的作用:替代xml配置文件!


2、Java中的注解:

@Overrid:作用在方法上的注解。当方法不是重写父类的方法时会报错;
@Deprecated:作用在方法上。标记该方法为作废方法(已过时);
@SuppressWarnings:作用在方法上,压制警告

3、注解的使用:

定义注解类:框架的工作
使用注解:我们的工作
读取注解(反射):框架的工作

4、定义注解类:

定义注解类不能使用class、enum,也不能使用interface,而是使用@interface
eg.   

[java] view
plain copy

public @interface MyAnn{}    

5、使用注解的目标:

注解可以使用在类(接口或枚举)、属性、方法、构造器、包、参数、局部变量

eg.

[java] view
plain copy

package cn.ywq;    

    

@MyAnn    

public class MyClass {    

    @MyAnn    

    private int a;    

    @MyAnn    

    public MyClass() {}    

    @MyAnn    

    public void fun1() {}    

    @MyAnn    

    public void fun2(@MyAnn String s) {    

        @MyAnn    

        int n = 10;    

    }    

}    

6、注解的属性:

定义注解时,也可以给出属性。

[java] view
plain copy

public @interface MyAnn {    

    String value();    

    int value1();    

}  

其中value就是属性!你可能会说,它是一个方法!没错,它是一个方法,但我们非要称之为属性,因为把它当做属性更加好理解。当为注解指定属性后,那么在使用注解时就必须要给属性赋值了:

[java] view
plain copy

@MyAnn(value1=100,value="hello")    

public class MyClass {    

}   

注解的属性还可以有默认值,在使用注解时就可以不给带有默认值的属性赋值了。但没有给出默认值的属性还是要赋值的。

[java] view
plain copy

public @interface MyAnn {    

    String value() default "hello world";     

    int value1();    

}    

@MyAnn(value1=100)     

public class MyClass {    

}   

在使用注解时,如果只给名为value的属性赋值,那么可以不给出属性的名称直接给出值

[java] view
plain copy

public @interface MyAnn {    

    String value() default "hello world";    

    int value1() default 100;    

}    

@MyAnn()     

public class MyClass {    

}    

@MyAnn(value="hello")     

public class MyClass {    

}    

@MyAnn(value1=200)     

public class MyClass {    

}    

@MyAnn(value="hello",value1=200)     

public class MyClass {    

}    

@MyAnn("hello annocation")     

public class MyClass {    

}    

@MyAnn(300)     

public class MyClass {    

}    

@MyAnn("hello",value1=200)     

public class MyClass {    

}    

 cop

注解的属性后面要有一对圆括号,而且圆括号内不能给出东西。就像是无参的方法一样;
注解的属性类型只能是:基本类型、String、Enum、Class、注解类型、以上类型的一维数组类型;
注解的属性可以有默认值,例如:int a() default 100;
数组的属性默认值:int[] arr() default {1,2,3},这里不能使用new int[]{1,2,3}
使用注解时,在给数组属性赋值时的格式:@MyAnn(arr={1,2,3});

注解属性的类型
    > 8种基本类型

    > String

    > Enum

    > Class

    > 注解类型

    > 以上类型的一维数组类型

    当给数组类型的属性赋值时,若数组元素的个数为1时,可以省略大括号。


eg

[java] view
plain copy

@MyAnno1(   //相当于一个注解对象    

    a=100,    

    b="hello",    

    c=MyEnum1.A,    

    d=String.class,    

    e=@MyAnno2(aa=200, bb="world"),    所以此处e也得是一个注解对象    

    f=100    //省略了大括号    

)    

public class Demo3 {    

    

}    

    

@interface MyAnno1 {    

    int a();    

    String b();    

    MyEnum1 c();    

    Class d();    

    MyAnno2 e();    

    int[] f();    

}    

@interface MyAnno2{    

       int aa();    

       String bb();    

}   

 

7、注解的作用目标:(@Target)

在定义注解时可以限制注解的作用目录!例如让注解只能作用在类和方法上。

这需要使用元注解:@Target。该注解有一个属性value,类型为ElementType[],它是枚举类型。

Target注解的源码如下:

[java] view
plain copy

public @interface Target {    

    ElementType[] value();    

}    

public enum ElementType {    

  TYPE,FIELD,METHOD,PARAMETED,CONSTRUCTOR,LOCAL_VARIABLE,ANNOCATION_TYPE,PACKAGE    

}    

在定义注解时,可以使用@Target注解来限制注解的作用目标:

[java] view
plain copy

@Target({ElementType.TYPE, ElementType.METHOD})    

public @interface MyAnn {    

}  

这样MyAnn就只能作用在类和方法上的!其中ElementType.TYPE表示类和接口。

[java] view
plain copy

@MyAnn()    

public class MyClass {    

    @MyAnn()  //报错    

    private int a;    

        

    @MyAnn()    

    public void fun() {}    

}   

 copy

8、注解的保留策略:(@Rentention)

注解的保留策略是指,注解是只保留在源代码上,还是保留到class文件上,再或者是类在运行时,可以被类加载器加载到内存中。
如果希望注解被反射,那么注解就要保留到运行时,而不是源代码或类文件上。
指定注解的保留策略需要使用元注解@Retention,它有一个value属性,类型为RetentionPolicy类型,RetentionPolicy是枚举类型

[java] view
plain copy

public @interface Retention {    

    RetentionPolicy value();    

}    

public enum RetentionPolicy {    

    SOURCE, CLASS, RUNTIME    

}   

下面代码是指定注解保留到运行时:

[java] view
plain copy

@Retention(RetentionPolicy.RUNTIME)    

@Target({ElementType.TYPE, ElementType.METHOD})    

public @interface MyAnn {    

    String value() default "hello";    

    int value1() default 100;    

}    

9、注解处理器

 view
plain cop

前面我们介绍了如何定义一个注解,并且阐述了定义注解的属性以及注解可以使用的位置等。那么我们的注解如何才能开始工作呢?即我们的注解内部该如何处理?这个时候我们就需要定义一个注解处理器了。

注解处理器定义了该注解的处理逻辑,下边我们举例说明。

要求:定义一个注解 @Retry ,该注解的功能是每隔一定的时间执行一次该方法,一共执行指定的次数。

好的,根据题意,我们可以定义如下的注解。

[java] view
plain copy

import java.lang.annotation.Retention;  

import java.lang.annotation.Target;  

import java.lang.annotation.ElementType;  

import java.lang.annotation.RetentionPolicy;  

  

@Target(ElementType.METHOD) // 指明该注解的作用范围是方法上  

@Retention(RetentionPolicy.RUNTIME)  // 指明该注解在运行时仍保留  

public @interface Retry {  

    int interval() default 3; // 定义属性,并且拥有默认值  

    int time() default 3000;  

}  

接着是我们的注解处理器:

[java] view
plain copy

// 注解处理器,定义注解的逻辑处理  

class RetryProcessor {  

    public void parseMethod(Class<?> clazz) throws Exception{  

        Method[] methods = clazz.getDeclaredMethods(); // 根据.class得到 该类中的method  

        for(final Method method : methods){  

            Retry retry = method.getAnnotation(Retry.class); // 得到该method上的注解信息,可以为null  

            if(retry != null){  

                final int interval = retry.interval();  // 获得注解的属性  

                final int time = retry.time();  

                // 建立一个线程,并且执行method.invoke()方法  

                ExecutorService executorService = Executors.newFixedThreadPool(2);  

                executorService.execute(new Runnable() {  

                    @Override  

                    public void run() {  

                        for (int i = 0; i < interval; i++) {  

                            try {  

                                // 通过反射执行方法  

                                method.invoke(new Object(), "57890");  

                                Thread.sleep(time);  

                            } catch (Exception e) {  

                                e.printStackTrace();  

                            }  

                        }  

                    }  

                });  

            }  

        }  

    }  

}  

测试类如下:

[java] view
plain copy

public class RetryTest {  

    /*@Retry 

    public static void sayHello(){ 

        System.out.println("Hello World"); 

    }*/ 如果要使用该方法时,method.invoke(new Object(),null)即可  

    @Retry  

    public static void sayHello(String name){  

        System.out.println("say hello1 " + name);  

    }  

    @Retry(interval = 2, time = 9000)  

    public static void sayHello2(String name){  

        System.out.println("say hello2 " + name);  

    }  

    public static void main(String[] args) throws Exception {  

        RetryProcessor retry = new RetryProcessor();  

        retry.parseMethod(RetryTest.class);  

    }  

}  

如此,我们即定义了一个完整的注解@Retry,实现了在每隔固定的时间执行方法一次,一共执行指定的次数。

总结:

1、注解的定义使用@interface标识

2、注解可以定义属性,并且可以拥有默认值

3、注解可以作用在类(接口或枚举)、属性、方法、构造器、包、参数、局部变量。

4、注解处理器定义了注解的处理逻辑,涉及到反射机制、线程机制等。

如果对你有帮助,记得点赞哦~欢迎大家关注我的博客,可以进群366533258一起交流学习哦~

本群给大家提供一个学习交流的平台,内设菜鸟Java管理员一枚、精通算法的金牌讲师一枚、Android管理员一枚、蓝牙BlueTooth管理员一枚、Web前端管理一枚以及C#管理一枚。欢迎大家进来交流技术。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: