枚举

什么是枚举

枚举(Enum)是在Java 5中添加的新的类型,技术上来讲,由于enum是一个类,一个enum可以有构造方法和方法。如果有构造方法,那必须是私有的。如果一个enum定义了枚举值之外的其他内容,枚举值必须在其他内容之前定义,并且最后的枚举值用一个分号结束。

枚举的使用

  • 创建枚举
enum Letter{
	A,B,C,D
}
  • 使用枚举
    定义了枚举后,可以创建枚举类型的变量,但是不能使用new关键字来实例化枚举,而是通过与基本类型类似的方式声明:
Letter letter1=Letter.A;
Letter letter2=Letter.B;
  • 可以使用关系运算符“==”来比较两个枚举变量的相等性
if (letter1 == letter2) {
	System.out.println("相等");
} else {
	System.out.println("不相等");
}
  • 枚举值也可以用于控制switch语句
switch (letter1) {
    case A:
    	System.out.println("A");
    	break;
    case B:
    	System.out.println("B");
    	break;
}

枚举的限制

  • 枚举不能继承其他类。但是所有枚举都隐式自动继承超类java.lang.Enum
  • 枚举不能是超类,不能进行扩展

枚举的常用方法

  • values() 返回一个包含枚举常量列表的数组
  • valuesOf(String) 返回与传递的字符串参数相对应的枚举常量
  • ordinal() 返回枚举常量在常量列表中位置的值,这称为枚举常量的序数值
  • compareTo(Enum) 方法用于比较相同类型的两个枚举常量的序数值
  • equals(Enum) 用于比较两个对象的相等性,只有两个对象都引用同一个枚举中相同的常量时,返回值才为true

注解

元数据

要想理解注解(Annotation)的作用,就要先理解Java中元数据的概念。在编程语言上下文中,元数据是添加到程序元素如方法、字段、类和包上的额外信息。对数据进行说明描述的数据。

  • 元数据的作用
  • 编写文档:通过代码里标识的元数据生成文档
  • 代码分析:通过代码里标识的元数据对代码进行分析
  • 编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查
  • 元数据与注解的关系
    注解Annotation就是java平台的元数据,是J2SE5.0新增加的功能,该机制允许在Java代码中添加自定义注释,并允许通过反射(reflection),以编程方式访问元数据注释。通过提供为程序元素(类、方法等)附加额外数据的标准方法,元数据功能具有简化和改进许多应用程序开发领域的潜在能力,其中包括配置管理、框架实现和代码生成。

注解的属性分类

标准Annotation(内建注解)

包括 Override、Deprecated、SuppressWarnings、@FunctionalInterface,是java自带的几个注解,他们由编译器来识别,不会进行编译, 不影响代码运行。

  • @Override
    用于告知编译器,我们需要覆写超类的当前方法。如果某个方法带有该注解但并没有覆写超类相应的方法,则编译器会生成一条错误信息。如果父类没有这个要覆写的方法,则编译器也会生成一条错误信息。@Override可适用元素为方法,仅仅保留在java源文件中。
  • @Deprecated
    用于告知编译器,某一程序元素(比如方法,成员变量)不建议使用了(即过时了)。
  • @SuppressWarnings
    用于告知编译器忽略特定的警告信息,例在泛型中使用原生数据类型,编译器会发出警告,当使用该注解后,则不会发出警告。适合用于除注解类型声明和包名之外的所有元素,仅仅保留在java源文件中。该注解有方法value(),可支持多个字符串参数,用户指定忽略哪种警告,例如:
@SupressWarning(value={"uncheck","deprecation"})
  • @FunctionalInterface
    用于告知编译器,检查这个接口,保证该接口是函数式接口,即只能包含一个抽象方法,否则就会编译出错。@FunctionalInterface可适合用于注解类型声明,保留时长为运行时。

元Annotation

JDK除了在java.lang提供了上述内建注解外,还在java.lang.annotation包下提供了6个Meta Annotation(元Annotataion),其中有5个元Annotation都用于修饰其他的Annotation定义。其中@Repeatable专门用户定义Java 8 新增的可重复注解,@Retention、@Target、@Inheritd、@Documented,它们是用来定义Annotation的Annotation。当我们需要自定义注解时,需要使用他们。

  • @Documented
    @Documented用户指定被该元Annotation修饰的Annotation类将会被javadoc工具提取成文档,举个🌰:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

定义@Deprecate时使用了@Documented,则任何元素使用@Deprecate修饰时,在生成API文档时,将会包含@Deprecated的说明。

  • @Inherited
    @Inherited指定被它修饰的Annotation将具有继承性——如果某个类使用了@Xxx注解(定义该Annotation时使用了@Inherited修饰)修饰,则其子类将自动被@Xxx修饰。
  • @Retention
    表示该注解类型的注解保留的时长。当注解类型声明中没有@Retention元注解,则默认保留策略为RetentionPolicy.CLASS,具体的使用在自定义注解会讲到,这里不过多赘述。
  • @Target
    表示该注解类型的所适用的程序元素类型。当注解类型声明中没有@Target元注解,则默认为可适用所有的程序元素。如果存在指定的@Target元注解,则编译器强制实施相应的使用限制。关于程序元素(ElementType)是枚举类型,共定义8种程序元素,如下表:

自定义Annotation

  • 自定义Annotation分类,通过元Annotation - @Retention 定义:
  • @Retention(RetentionPolicy.SOURCE)
  • 源码时注解,一般用来作为编译器标记。如Override, Deprecated, SuppressWarnings。
  • 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;源码注解(RetentionPolicy.SOURCE)的生命周期只存在Java源文件这一阶段,是3种生命周期中最短的注解。当在Java源程序上加了一个注解,这个Java源程序要由javac去编译,javac把java源文件编译成.class文件,在编译成class时会把Java源程序上的源码注解给去掉。需要注意的是,在编译器处理期间源码注解还存在,即注解处理器Processor 也能处理源码注解,编译器处理完之后就没有该注解信息了。
  • @Retention(RetentionPolicy.CLASS)
  • 编译时注解,在编译时被识别并处理的注解,这是本章重点。
  • 编译时注解能够自动处理Java源文件并生成更多的源码、配置文件、脚本或其他可能想要生成的东西。
  • @Retention(RetentionPolicy.RUNTIME)
  • 运行时注解,在运行时通过反射去识别的注解。
  • 定义运行时注解,只需要在声明注解时指定@Retention(RetentionPolicy.RUNTIME)即可。
  • 运行时注解一般和反射机制配合使用,相比编译时注解性能比较低,但灵活性好,实现起来比较简单。

此外,注解还可以按照运行的时段分为编译器注解和运行期注解两大类。
运行时注解:retrofit
编译时注解:Dagger2、ButterKnife、EventBus3