Java学习笔记10-枚举类与注解
一、枚举类
1、什么是枚举类
类的对象只有有限个,确定的,称此类为枚举类。比如星期、性别、季节、xx状态等。
当需要定义一组常量时,强烈建议使用枚举类。
如果枚举类中只有一个对象,则可以作为单例模式的实现方式。
属性:
- 枚举类对象的属性不应允许被改动,所以应该使用
private final
修饰。 - 枚举类中使用
private final
修饰的属性应该在构造器中为其赋值。 - 若枚举类显式地定义了带参数的构造器,则在列出枚举值时也应该对应地传入参数。
2、自定义枚举类
JDK 5.0之前,没有enum
关键字,只能自定义枚举类,步骤为:
- 私有化类的构造器,保证不能在类的外部创建其对象。
- 在类的内部创建枚举类的实例,声明为:
public static final
- 对象如果有实例变量,应该声明为
private final
,并在构造器中初始化。
举例说明:
1 |
|
3、使用enum定义枚举类
JDK 5.0新增了enum
定义枚举类的方式,使用enum
定义的枚举类默认继承了java.lang.Enum
类,因此不能再继承其他类。
使用说明:
- 枚举类的构造器只能使用
private
权限修饰符。 - 枚举类的所有实例必须在枚举类中显式列出(以
,
分隔,以;
结尾)。列出的实例,系统会自动添加public static final
修饰。 - 必须在枚举类的第一行声明枚举类对象。
JDK 5.0中,switch
表达式中可以使用枚举类对象,case
子句可以直接使用枚举值的名字,无需添加枚举类作为限定。
使用enum
定义枚举类:
1 |
|
4、Enum类
Enum
类有以下几个常用方法:
values()
:静态方法,枚举类调用此方法返回包含此枚举类中所有枚举对象的枚举类型的对象数组。这个方法是Java编译器在编译枚举类的时候自动添加的方法。valueOf(String str)
:把一个字符串str转为对应的枚举类对象。要求str‘必须是枚举类对象的“名字”。如不是,会有运行时异常IllegalArgumentException
。toString
:可以被重写public final boolean equals
:枚举类中可以直接使用==
比较两个枚举常量是否相等,Enum类中的equals
方法也是直接使用==
实现的,此方法是为了在Set、List和Map中使用。public final int hashCode
getDeclaringClass
:得到枚举常量所属枚举类型的Class对象,可以用来判断两个枚举常量是否属于同一个枚举类型name
:得到当前枚举常量的名字。ordinal
:得到当前枚举常量的次序。compareTo
:枚举类型实现了Comparable接口,比较两个枚举常量的大小(按照声明的顺序排列)protected final Object clone
:枚举类型不能被Clone,为了防止子类实现克隆方法,Enum实现了一个仅抛出CloneNotSupportedException
异常的final
方法clone()
。
代码举例:
1 |
|
5、枚举类实现接口
和普通Java类一样,枚举类可以实现一个或多个接口:
- 若每个枚举值在调用实现的接口方法呈现相同的行为方式,则只要统一实现该方法即可。
- 若需要每个枚举值在调用实现的接口方法呈现出不同的行为方式,则可以让每个枚举值分别来实现该方法。
比如下面的代码:
1 |
|
二、注解
1、概述
JDK 5.0开始支持注解(Annotation),注解是代码里的特殊标记,可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用注解,可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者部署。
Annotation可以像修饰符一样被使用,可用于修饰包,类,构造器,方法,成员变量,参数,局部变量的声明,这些信息被保存在Annotation的“name=value”对中。
在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和XML配置等。
框架 = 注解 + 反射 + 设计模式
2、常见注解
常见的注解主要用三种用处:
1、生成文档相关的注解。
@author标明开发该类模块的作者,多个作者之间使用,分割
@version标明该类模块的版本@see参考转向,也就是相关主题
@since表示从哪个版本开始增加的
@param对方法中某参数的说明,如果没有参数就不能写
@return对方法返回值的说明,如果方法的返回值类型是void就不能写
@exception对方法可能抛出的异常进行说明,如果方法没有用throws显式抛出的异常就不能写
其中
- @param@return和@exception这三个标记都是只用于方法的。
- @param的格式要求:@param形参名形参类型形参说明
- @return的格式要求:@return返回值类型返回值说明
- @exception的格式要求:@exception异常类型异常说明
- @param和@exception可以并列多个
例如:
1 |
|
2、编译时进行格式检查(JDK内置的三个基本注解)
@Override
:限定重写父类方法,该注解只能用于方法。@Deprecated
:用于表示所修饰的元素(类、方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择@SuppressWarnings
:抑制编译器警告。
3、跟踪代码依赖性,实现替代配置文件的功能。例如Serverlet3.0中注解使得不再需要在web.xml文件中进行Servlet部署:
3、自定义注解
自定义注解使用@interface
关键字,并且自动继承了java.lang.annotation.Annotation
接口。
注解的成员变量在Annotation定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型,称之为配置参数。类型只能是八种基本数据类型、String类型、Class类型、enum类型、Annotation类型以及以上类型的数组。
定义注解成员变量时如果指定初始值,可以使用
default
关键字。- 如果只有一个参数成员,建议使用参数名为
value
- 如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是
参数名=参数值
,如果只有一个参数成员,且名称为value
,可以省略value=
- 没有成员定义的
Annotation
称为标记
;包含成员变量的Annotation
称为元数据Annotation
。
自定义注解必须配上注解的信息处理流程才有意义。
自定义注解举例:
1 |
|
4、元注解
用于修饰其他注解的注解,就是元注解(meta-annotation)
。
JDK 5.0提供了4个标准的元注解:
@Retention
:指定被修饰的注解的生命周期。@Target
:指定被修饰的注解能够用于修饰哪些程序元素。@Documented
:表示所修饰的注解在被javadoc
解析时保留下来。@Inherited
:被修饰的注解将具有继承性。
1、@Retention
@Retentio
元注解用于定义Annotation
的生命周期,其包含一个RetentionPolicy
类型的成员变量,使用@Retention
元注解时,必须为该成员变量指定值,有以下三种值(枚举变量):
RetentionPolicy.SOURCE
:在源文件中有效(即源文件中保留),编译器直接丢弃这种策略的注释RetentionPolicy.CLASS
:在class文件中有效(即class保留),运行Java程序时,JVM不会保留这种注解。这是默认值。RetentionPolicy.RUNTIME
:在运行时有效(即运行时保留),运行Java程序时,JVM会保留注释。程序可以通过反射获取该注释。
如下图:
使用举例:
1 |
|
2、@Target
@Target
用于指定被修饰的Annotation
能用于修饰哪些元素,@Target
包含一个名为value的数组成员变量,可以取以下的值:
取值 | 含义 |
---|---|
ElementType.CONSTRUCTOR |
用于描述构造器 |
ElementType.PACKAGE |
用于描述包 |
ElementType.FIELD |
用于描述域(包括枚举常量) |
ElementType.TYPE |
用于描述类、接口(包括注解类型)或enum声明 |
ElementType.METHOD |
用于描述方法 |
ElementType.LOCAL_VARIABLE |
用于描述局部变量 |
ElementType.PARAMETER |
用于描述参数 |
3、@Documented
@Documented
用于指定被改元注解修饰的注解类将被javadoc
工具提取成文档。默认情况下,javadoc
不包括注解。
定义为Documented
的注解必须设置Retention
的值为RUNTIME
。
4、@Inherited
@Inherited
修饰的注解具有继承性,其子类自动具有该注解,即该注解类的子类可以继承父类级别的注解。
5、反射获取注解信息
JDK 5.0在java.lang.reflect包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素。
当一个Annotation类型被定义为运行时Annotation后,该注解才是运行时可见,当class文件被载入时保存在class文件中的Annotation才会被虚拟机读取。
程序可以调用AnnotatedElement对象的如下方法来访问Annotation信息:
getAnnotation(Class<T> annotatoinClass)
getAnnotations()
getDeclaredAnnotations()
isAnnotationPresent(Class<? extends Annotation> annotationClass)
6、JDK 8中注解新特征
JDK 8.0新增了可重复注解和类型注解。
1、可重复注解
- a. 在
MyAnnotation
上声明@Repeatable
,成员值为MyAnnotations.class
,此时的MyAnnotations
为容器注解。 - b. 要求
MyAnnotation
的@Target
和@Retention
等元注解与MyAnnotations
相同。
使用示例:
1 |
|
2、类型注解
JDK 8.0之后,元注解@Target
的参数类型ElementType
枚举值多了两个:TYPE_PARAMETER
和TYPE_USE
。在JDK 8.0之前,注解只能是在声明的地方所使用,Java8开始,注解可以应用在任何地方。
ElementType.TYPE_PARAMETER
:表示该注解能写在类型变量的声明语句中(如:泛型声明)。ElementType.TYPE_USE
:表示该注解能写在使用类型的任何语句中。
比如,同样使用上面的@MyAnnotation
,其元注解@Target
的参数包括了TYPE_PARAMETER
和TYPE_USE
,表明该注解可以写在类型变量的声明语句中,也能写在使用类型的任何语句中:
1 |
|
- 本文作者:Kangshitao
- 本文链接:http://kangshitao.github.io/2021/04/05/java-note-1001/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!