zoukankan      html  css  js  c++  java
  • Java基础(十)——枚举与注解 Craftsman

    一、枚举

    1、介绍

      枚举类:类的对象只有有限个,确定的。当需要定义一组常量时,强烈建议使用枚举类。如果枚举类中只有一个对象,则可以作为单例模式的实现。
      使用 enum 定义的枚举类默认继承了 java.lang.Enum类,因此不能再继承其他类。

    2、枚举的实现

      代码示例:方式一,JDK 5.0 之前,自定义枚举类

     1 public class SeasonEnum {
     2 
     3     // 枚举当前类的多个对象
     4     public static final SeasonEnum SPRING = new SeasonEnum("01", "春天");
     5     public static final SeasonEnum SUMMER = new SeasonEnum("02", "夏天");
     6     public static final SeasonEnum AUTUMN = new SeasonEnum("03", "秋天");
     7     public static final SeasonEnum WINTER = new SeasonEnum("04", "冬天");
     8 
     9     private SeasonEnum(String code, String desc) {
    10         this.code = code;
    11         this.desc = desc;
    12     }
    13 
    14     private final String code;
    15     private final String desc;
    16 
    17     public String getCode() {
    18         return code;
    19     }
    20 
    21     public String getDesc() {
    22         return desc;
    23     }
    24 }

      代码示例:方式二,JDK 5.0,可以使用 enum 关键字定义枚举

     1 public enum SeasonEnum {
     2 
     3     // 枚举当前类的多个对象
     4     SPRING("01", "春天"),
     5     SUMMER("02", "夏天"),
     6     AUTUMN("03", "秋天"),
     7     WINTER("04", "冬天");
     8 
     9     public static final Map<String, SeasonEnum> map = new HashMap<>();
    10 
    11     static {
    12         for (SeasonEnum e : values()) {
    13             map.put(e.code, e);
    14         }
    15     }
    16 
    17     SeasonEnum(String code, String desc) {
    18         this.code = code;
    19         this.desc = desc;
    20     }
    21 
    22     private final String code;
    23     private final String desc;
    24 
    25     public String getCode() {
    26         return code;
    27     }
    28 
    29     public String getDesc() {
    30         return desc;
    31     }
    32 
    33 }

    3、枚举实现接口

     1 public enum SeasonEnum implements Info {
     2 
     3     // 枚举当前类的多个对象
     4     SPRING("01", "春天") {
     5         @Override
     6         public void show() {
     7             System.out.println("春暖花开");
     8         }
     9     },
    10     SUMMER("02", "夏天") {
    11         @Override
    12         public void show() {
    13             System.out.println("夏日炎炎");
    14         }
    15     },
    16     AUTUMN("03", "秋天"),
    17     WINTER("04", "冬天");
    18 
    19     SeasonEnum(String code, String desc) {
    20         this.code = code;
    21         this.desc = desc;
    22     }
    23 
    24     private final String code;
    25     private final String desc;
    26 
    27     public String getCode() {
    28         return code;
    29     }
    30 
    31     public String getDesc() {
    32         return desc;
    33     }
    34 
    35     public void show() {
    36         System.out.println("我的天气");
    37     }
    38 
    39 }
    40 
    41 interface Info {
    42     void show();
    43 }

    4、API

      values()方法:返回所有的枚举类型的对象。
      valueOf(String str):检查该字符串是不是枚举类对象的"名字"。如不是,会有运行时异常:IllegalArgumentException。
      toString():返回当前枚举类对象常量的名称。

    二、注解

    1、介绍

      从 JDK 5.0 开始,Java 增加了对元数据(MetaData)的支持,也就是Annotation(注解)。
      Annotation 其实就是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用 Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。
      一定程度上,可以说:框架 = 注解 + 反射 + 设计模式。

    2、示例

      示例一、生成文档相关

      @author:标明开发该类模块的作者,多个作者之间使用,分割。
      @version:标明该类模块的版本。
      @see:参考转向,也就是相关主题。
      @since:从哪个版本开始增加的。
      @param:对方法中某参数的说明,如果没有参数就不能写。
      @return:对方法返回值的说明,如果方法的返回值类型是void就不能写。
      @exception:对方法可能抛出的异常进行说明,如果方法没有用throws显式抛出的异常就不能写。

      示例二、在编译时进行格式检查(JDK内置的三个基本注解)

      @Override:限定重写父类方法,该注解只能用于方法。
      @Deprecated:用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择。
      @SuppressWarnings:抑制编译器警告。

    3、自定义注解

      代码示例:

     1 @Retention(RetentionPolicy.RUNTIME)
     2 @Target({ElementType.TYPE, ElementType.FIELD})
     3 public @interface MyAnnotation {
     4     String value() default "baidu";
     5 }
     6 
     7 @MyAnnotation()
     8 public class Person {
     9 }
    10     
    11 public class Main {
    12     public static void main(String[] args) {
    13         // 通过反射获取Person类的注解
    14         Class<Person> clazz = Person.class;
    15         MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
    16 
    17         // 获取注解的值
    18         String value = annotation.value();
    19         System.out.println(value); // baidu(输出了默认值)
    20     }
    21 }

    4、元注解

      JDK 的元注解用于修饰其他注解定义。除了上面自定义注解用到的两个,JDK5.0提供了4个标准的元注解,分别是:@Documented、@Inherited、@Retention、@Target。
      @Retention:用于指定注解的生命周期,它包含一个RetentionPolicy枚举类型的成员变量。
      源码示例:

     1 @Documented
     2 @Retention(RetentionPolicy.RUNTIME)
     3 @Target(ElementType.ANNOTATION_TYPE)
     4 public @interface Retention {
     5     /**
     6      * Returns the retention policy.
     7      * @return the retention policy
     8      */
     9     RetentionPolicy value();
    10 }
    11     
    12 public enum RetentionPolicy {
    13     /**
    14      * Annotations are to be discarded by the compiler.
    15      */
    16     SOURCE,
    17 
    18     /**
    19      * Annotations are to be recorded in the class file by the compiler
    20      * but need not be retained by the VM at run time.  This is the default
    21      * behavior.
    22      */
    23     CLASS,
    24 
    25     /**
    26      * Annotations are to be recorded in the class file by the compiler and
    27      * retained by the VM at run time, so they may be read reflectively.
    28      *
    29      * @see java.lang.reflect.AnnotatedElement
    30      */
    31     RUNTIME
    32 }

      源码中的英文注释写的很清楚,下面翻译一下:
      RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释。
      RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行 Java 程序时,JVM不会保留注解。这是默认值。
      RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行 Java 程序时,JVM 会保留注释。只有声明为RUNTIME生命周期的注解,才可以通过反射获取该注释。
      @Target:用于指定注解能用于修饰哪些程序元素,它包含一个ElementType枚举类型的成员变量。
      源码示例:

     1 @Documented
     2 @Retention(RetentionPolicy.RUNTIME)
     3 @Target(ElementType.ANNOTATION_TYPE)
     4 public @interface Target {
     5     ElementType[] value();
     6 }
     7 
     8 public enum ElementType {
     9     // 用于修饰类、接口,或者enum声明
    10     /** Class, interface (including annotation type), or enum declaration */
    11     TYPE,
    12     
    13     // 用于修饰域
    14     /** Field declaration (includes enum constants) */
    15     FIELD,
    16     
    17     // 用于修饰方法
    18     /** Method declaration */
    19     METHOD,
    20     
    21     // 用于修饰参数
    22     /** Formal parameter declaration */
    23     PARAMETER,
    24     
    25     // 用于修饰构造器
    26     /** Constructor declaration */
    27     CONSTRUCTOR,
    28     
    29     // 用于修饰局部变量
    30     /** Local variable declaration */
    31     LOCAL_VARIABLE,
    32     
    33     // 用于修饰注解
    34     /** Annotation type declaration */
    35     ANNOTATION_TYPE,
    36     
    37     // 用于修饰包
    38     /** Package declaration */
    39     PACKAGE,
    40 
    41     /**
    42      * Type parameter declaration
    43      *
    44      * @since 1.8
    45      */
    46     TYPE_PARAMETER,
    47 
    48     /**
    49      * Use of a type
    50      *
    51      * @since 1.8
    52      */
    53     TYPE_USE
    54 }

      @Documented:用于指定被该注解修饰的类将被 javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。定义为Documented的注解必须设置Retention值为RUNTIME。
      @Inherited:被它修饰的注解将具有继承性。如果某个类使用了被@Inherited 修饰的注解,则其子类将自动具有该注解。

    三、JDK8的新特性

    1、介绍

      Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。此外,反射也得到了加强,在Java8中能够得到方法参数的名称。这会简化标注在方法参数上的注解。

    2、可重复注解

      代码示例:方式一,JDK8之前

     1 @Retention(RetentionPolicy.RUNTIME)
     2 @Target({ElementType.TYPE})
     3 public @interface MyAnnotation {
     4     String value() default "baidu";
     5 }
     6 
     7 @Retention(RetentionPolicy.RUNTIME)
     8 @Target({ElementType.TYPE})
     9 public @interface MyAnnotations {
    10     MyAnnotation[] value();
    11 }
    12 
    13 //@MyAnnotation("xiaoming")
    14 //@MyAnnotation("xiaohong")
    15 @MyAnnotations({@MyAnnotation("xiaoming"), @MyAnnotation("xiaohong")})
    16 public class Person {
    17     private int age;
    18 
    19     public void say() {
    20     }
    21 }

      代码示例:方式二,JDK8之后

     1 // 注:MyAnnotation的Target和Retention等元注解须与MyAnnotations相同
     2 @Repeatable(MyAnnotations.class)
     3 @Retention(RetentionPolicy.RUNTIME)
     4 @Target({ElementType.TYPE})
     5 public @interface MyAnnotation {
     6     String value() default "baidu";
     7 }
     8 
     9 @Retention(RetentionPolicy.RUNTIME)
    10 @Target({ElementType.TYPE})
    11 public @interface MyAnnotations {
    12     MyAnnotation[] value();
    13 }
    14 
    15 @MyAnnotation("xiaoming")
    16 @MyAnnotation("xiaohong")
    17 public class Person {
    18     private int age;
    19 
    20     public void say() {
    21     }
    22 }

    3、类型注解

      在Java 8之前,注解只能在声明的地方使用。Java8开始,注解可以应用在任何地方。
      ElementType.TYPE_PARAMETER:表示该注解能写在类型变量的声明语句中(如:泛型声明)。
      ElementType.TYPE_USE:表示该注解能写在使用类型的任何语句中。
      代码示例:TYPE_PARAMETER

     1 @Retention(RetentionPolicy.RUNTIME)
     2 @Target({ElementType.TYPE, ElementType.TYPE_PARAMETER})
     3 public @interface MyAnnotation {
     4     String value() default "baidu";
     5 }
     6 
     7 @MyAnnotation
     8 public class Person<@MyAnnotation T> {
     9     private T age;
    10 
    11     public void say() throws RuntimeException {
    12         List<String> list = new ArrayList<>();
    13 
    14         int num = (int) 10L;
    15     }
    16 }

      代码示例:TYPE_USE

     1 @Retention(RetentionPolicy.RUNTIME)
     2 @Target({ElementType.TYPE, ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
     3 public @interface MyAnnotation {
     4     String value() default "baidu";
     5 }
     6 
     7 @MyAnnotation
     8 public class Person<@MyAnnotation T> {
     9     private T age;
    10 
    11     public void say() throws @MyAnnotation RuntimeException {
    12         List<@MyAnnotation String> list = new ArrayList<>();
    13 
    14         int num = (@MyAnnotation int) 10L;
    15     }
    16 }

    作者:Craftsman-L

    本博客所有文章仅用于学习、研究和交流目的,版权归作者所有,欢迎非商业性质转载。

    如果本篇博客给您带来帮助,请作者喝杯咖啡吧!点击下面打赏,您的支持是我最大的动力!

  • 相关阅读:
    嵌入式工程师为何不用学习C++语言?
    汽车电子基础知识
    为什么寄存器比存储器快?
    数字信号和模拟信号
    JLink和JTag的区别
    C++中static关键字作用总结
    所谓高情商,就是会说话
    汽车电子缩略语及术语
    卷积
    算法整理
  • 原文地址:https://www.cnblogs.com/originator/p/15737062.html
Copyright © 2011-2022 走看看