枚举
什么是枚举
枚举(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