0424 0442 第十一章 枚举和注解
11.1 先看一个需求¶
要求创建季节 (Season) 对象,请设计并完成。
11.2 分析问题¶
11.2.1 创建 Season 对象有如下特点¶
1) 季节的值是有限的几个值 (spring, summer, autumn, winter)
2) 只读,不需要修改。
11.3 解决方案-枚举¶
-
枚举对应英文 (enumeration, 简写 enum)
-
枚举是一组常量的集合。
-
可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。
11.4 枚举的二种实现方式¶
-
自定义类实现枚举
-
使用 enum 关键字实现枚举
11.5 自定义类实现枚举-应用案例¶
-
可以提供 get 方法,不需要提供
setXxx方法,因为枚举对象值通常为只读. -
对枚举对象 / 属性使用
final+static共同修饰,实现底层优化. -
枚举对象名通常使用全部大写,常量的命名规范.
-
枚举对象根据需要,也可以有多个属性
-
构造器私有化,防止被
new -
本类内部创建一组对象
-
对外暴露对象(通过为对象添加 public final static 修饰符)
public class Enumeration {
public static void main(String[] args) {
}
}
class Season {
private String Name;
private String desc;
//定义了四个对象, 固定.
public static final Season SPRING = new Season("春天", "温暖");
public static final Season WINTER = new Season("冬天", "寒冷");
public static final Season AUTUMN = new Season("秋天", "凉爽");
public static final Season SUMMER = new Season("夏天", "炎热");
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName(){
return name;
}
public String getDesc(){
return desc;
}
@Override
public String toString(){
return "Season{" +
"name = " + name + `\` +
",desc = "
}
}
11.7 enum 关键字实现枚举-快速入门¶
如果使用了 enum 来实现枚举类
-
使用关键字 enum 替代 class
-
public static final Season SPRING = new Season("春天", "温暖")直接使用SPRING("春天", "温暖")常量名(实参列表) -
如果有多个常量 (对象),使用 ,号间隔即可可
-
如果使用 enum 来实现枚举,要求将定义常量对象,写在最前面
-
如果我们使用的是无参构造器,创建常量对象,则可以省略 ()
SPRING,SUMMER
import java.util.Enumeration;
public class Main {
public static void main(String[] args) {
}
}
enum Season {
SPRING("春天", "春暖花开"),
SUMMER("夏天", "烈日炎炎"),
AUTUMN("秋天", "秋高气爽"),
WINTER("冬天", "冰天雪地");
private final String Name;
private final String Desc;
private Season(String name, String desc) {
this.Name = name;
this.Desc = desc;
}
public String getName() {
return Name;
}
public String getDesc() {
return Desc;
}
@Override
public String toString() {
return "Season{" +
"name = " + Name + ",desc = " + Desc +
'}';
}
}
¶
import java.util.Enumeration;
public class Main {
public static void main(String[] args) {
}
}
enum Season {
SPRING("春天", "春暖花开"),
SUMMER("夏天", "烈日炎炎"),
AUTUMN("秋天", "秋高气爽"),
WINTER("冬天", "冰天雪地");
private final String Name;
private final String Desc;
private Season(String name, String desc) {
this.Name = name;
this.Desc = desc;
}
public String getName() {
return Name;
}
public String getDesc() {
return Desc;
}
@Override
public String toString() {
return "Season{" +
"name = " + Name + ",desc = " + Desc +
'}';
}
}
11.7.2 enum 关键字实现枚举注意事项¶
-
当我们使用
enum关键字开发一个枚举类时,默认会继承Enum类, 而且是一个 final 类 -
传统的
public static final Season2 SPRING = new Season2("春天", "温暖");简化成SPRING("春天", "温暖"),这里必须知道,它调用的是哪个构造器 -
如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
-
当有多个枚举对象时,使用
,间隔,最后有一个分号结尾 -
枚举对象必须放在枚举类的行首
11.9 enum 常用方法说明¶
使用关键字 enum 时,会隐式继承 Enum 类, 这样我们就可以使用 Enum 类相关的方法。
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { }
11.10 enum 常用方法应用实例¶
| 方法名 | 描述 |
|---|---|
valueOf(Class<T> enumType, String name) |
传递枚举类型的 Class 对象和枚举常量名称给静态方法 valueOf,会得到与参数匹配的枚举常量。 |
toString() |
返回当前枚举常量的名称。可以通过重写此方法使返回结果更易读。 |
equals(Object other) |
在枚举类型中可以直接使用 == 比较两个枚举常量是否相等。Enum 提供的 equals 方法内部也是使用 == 实现,存在是为了在 Set、List 和 Map 中使用。注意,equals 返回的结果是不可变的。 |
hashCode() |
Enum 实现了 hashCode,与 equals 保持一致,返回值是不可变的。 |
getDeclaringClass() |
返回枚举常量所属枚举类型的 Class 对象,可用于判断两个枚举常量是否属于同一枚举类型。 |
name() |
返回当前枚举常量的名称。建议优先使用 toString 方法。 |
ordinal() |
返回当前枚举常量的次序(即在枚举声明中的位置,从 0 开始)。 |
compareTo(E o) |
枚举类型实现了 Comparable 接口,可比较两个枚举常量的大小(按声明顺序排列)。 |
clone() |
枚举类型不可克隆。Enum 实现的 clone 方法仅抛出 CloneNotSupportedException 异常,防止子类实现克隆。 |
11.11 enum 实现接口¶
-
使用
enum关键字后,就不能再继承其它类了,因为enum会隐式继承Enum,而 Java 是单继承机制。 -
枚举类和普通类一样,可以实现接口,如下形式。
enum 类名 implements 接口 1,接口 2{}
11.12 注解的理解¶
-
注解 (Annotation) 也被称为元数据 (Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。
-
和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
-
在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。
- 在 JavaEE 中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。
11.13 基本的 Annotation 介绍¶
使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。用于修饰它支持的程序元素
三个基本的 Annotation:
-
@Override: 限定某个方法,是重写父类方法, 该注解只能用于方法 -
@Deprecated: 用于表示某个程序元素 (类, 方法等) 已过时 -
@SuppressWarnings: 抑制编译器警告
11.14 基本的 Annotation 应用案例¶
11.14.1 @Override 注解¶
@Override: 限定某个方法,是重写父类方法, 该注解只能用于方法
class Father {
public void fly() {
System.out.println("Father fly...");
}
}
class Son extends Father {
@Override 〃说明
public void fly() {
System.out.println("Son fly....");
}
}
Override 源码:¶
@interface不是interface, 是注解类是 jdk 5.0 之后加入
@Target是修饰注解的注解,称为元注解, 记住这个概念.
@Override 使用说明¶
-
@Override表示指定重写父类的方法 (从编译层面验证),如果父类没有 fly 方法,则会报错 -
如果不写
@Override注解, 而父类仍有public void fly(){}, 仍然构成重写 -
@Override只能修饰方法,不能修饰其它类,包,属性等等 -
查看
@Override注解源码为@Target(ElementType.METHOD), 说明只能修饰方法 -
@Target是修饰注解的注解,称为元注解, 记住这个概念.
11.14.2 @Deprecated 注解¶
@Deprecated: 用于表示某个程序元素 (类, 方法等) 已过时代码
@Deorecated 源码¶
@Deprecated 使用说明¶
-
用于表示某个程序元素 (类, 方法等) 已过时
-
可以修饰方法,类,字段, 包, 参数等等
-
@Deprecated的作用可以做到新旧版本的兼容和过渡
11.14.3 @SuppressWarnings 注解¶
@SuppressWarnings: 抑制编译器警告
@Suppress@Warnings 的使用¶
//1. 当我们不希望看到这些警告的时候,可以使用 SuppressWarnings 注解来抑制警告信息
//2. 在{""} 中,可以写入你希望抑制(不显示)警告信息
//3. 可以指定的警告类型有
// all,抑制所有警告boxing,抑制与封装/拆装作业相关的警告
//cast,抑制与强制转型作业相关的警告
//dep-ann,抑制与淘汰注释相关的警告
//deprecation,抑制与淘汰的相关警告
//fallthrough,抑制与 switch 陈述式中遗漏 break 相关的警告
//finally,抑制与未传回 finally 区块相关的警告
//hiding,抑制与隐藏变数的区域变数相关的警告
//incomplete-switch,抑制与 switch 陈述式(enum case)中遗漏项目相关的警告
//javadoc,抑制与 javadoc 相关的警告|
//nls,抑制与非 nls 字串文字相关的警告
//null,抑制与空值分析相关的警告
//rawtypes,抑制与使用 raw 类型相关的警告
//resource,抑制与使用 Closeable 类型的资源相关的警告
//restriction,抑制与使用不建议或禁止参照相关的警告
//serial,抑制与可序列化的类别遗漏 serialVersionUID 栏位相关的警告
//static-access,抑制与静态存取不正确相关的警告
//static-method,抑制与可能宣告为 static 的方法相关的警告
//super,抑制与置换方法相关但不含 super 呼叫的警告
//synthetic-access,抑制与内部类别的存取未最佳化相关的警告
//sync-override,抑制因为置换同步方法而遗漏同步化的警告
//unchecked,抑制与未检查的作业相关的警告
//unqualified-field-access,抑制与栏位存取不合格相关的警告
//unused,抑制与未用的程式码及停用的程式码相关的警告
// 4. 关于 SuppressWarnings 作用范围是和你放置的位置相关
// 比如 @SuppressWarnings 放置在 main 方法,那么抑制警告的范围就是 main通常我们可以放置具体的语句, 方法, 类.
// 5. 看看 @SuppressWarnings 源码
//(1) 放置的位置就是 TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE
//(2) 该注解类有数组 String[] values() 设置一个数组比如 {"rawtypes", "unchecked", "unused"}
public static void main(String[] args) {
List list = new ArrayList(); list.add("jack"); list.add("tom"); list.add("mary");
int i; System.out.println(list.get(1));
}
public void f1() { // @SuppressWarnings({"rawtypes"})
List list = new ArrayList();
list.add("jack"); list.add("tom"); list.add("mary");
// @SuppressWarnings({"unused"}) int i; System.out.println(list.get(1));
}
| 参数名 | 描述 |
|---|---|
all |
抑制所有类型的警告(不推荐使用,过于宽泛)。 |
unchecked |
抑制与未检查的类型转换相关的警告,例如使用泛型时未指定类型。 |
deprecation |
抑制使用已废弃(过时)的方法、类或字段的警告。 |
rawtypes |
抑制使用原始类型(未指定泛型的类型)时的警告。 |
unused |
抑制未使用的变量、方法或类的警告。 |
null |
抑制与空指针分析相关的警告。 |
serial |
抑制缺少 serialVersionUID 的警告(适用于实现 Serializable 的类)。 |
cast |
抑制不安全的类型转换警告。 |
fallthrough |
抑制 switch 语句中 case 缺少 break 导致的穿透警告。 |
finally |
抑制 finally 块中可能导致资源泄漏的警告。 |
resource |
抑制未正确关闭资源(如 try-with-resources)的警告。 |
boxing |
抑制基本类型与包装类型之间自动装箱/拆箱的警告。 |
varargs |
抑制可变参数方法中可能导致的类型安全警告。 |
static-access |
抑制通过实例访问静态成员的警告。 |
synthetic-access |
抑制访问编译器生成的合成构造(如内部类访问外部类成员)的警告。 |
nls |
抑制非国际化字符串(非本地化字符串)的警告。 |
restriction |
抑制使用受限 API(如某些 Sun 内部 API)的警告。 |
说明
- @SuppressWarnings 注解用于抑制编译器生成的特定警告,需谨慎使用,避免隐藏真正的代码问题。
- 参数可以组合使用,例如 @SuppressWarnings({"unchecked", "deprecation"})。
- 建议将注解作用范围尽量缩小(如方法或变量级别),避免在整个类上使用。
SuppressWarnings 源码¶
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
@SuppressWarnings 的说明¶
-
unchecked是忽略没有检查的警告 -
rawtypes是忽略没有指定泛型的警告(传参时没有指定泛型的警告错误) -
unused是是忽略没有使用某个变量的警告错误. -
@SuppressWarnings可以可以修饰的程序元素为, 查看Target生成生成upperssWarnings时,不用背,直接点击左侧的黄色提示,就可以选择(注意可以指定生成的位置)
11.15 JDK 的元 Annotation (元注解,了解)¶
11.15.1 元注解的基本介绍¶
JDK 的元 Annotation 用于修饰其他 Annotation
11.15.2 元注解的种类¶
Retention//指定注解的作用范围,三种SOURCE,CLASS,RUNTIMETarget// 指定注解可以在哪些地方使用Documented//指定该注解是否会在 javadoc 体现Inherited//子类会继承父类注解
11.15.3 @Retention¶
只能用于修饰一个
Annotation定义, 用于指定该Annotation可以保留多长时间,@Rentention包含一个RetentionPolicy类型的成员变量,
- 使用
@Rentention时必须为该value成员变量指定值:
@Retention 的三种值
-
RetentionPolicy.SOURCE: 编译器使用后,直接丢弃这种策略的注释 -
RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解。这是默认值 -
RetentionPolicy.RUNTIME:编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注解
11.15.4 @Target¶
用于修饰
Annotation定义,用于指定被修饰的Annotation能用于修饰哪些程序元素 .
@Target 也包含一个名为 value 的成员变量
@Target 源码¶
@Documented
@Retention(RetentionPolicy.RUNTIME) // 作用范围是 RUNTIME
@Target(ElementType.ANNOTATIOP)// ANNOTATION_TYPE 说明 @Target 只能修饰注解
public ©interface Target { // 说明它是注解
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value。;
}
11.15.5 @Documented¶
@Documented: 用于指定被该元Annotation修饰的Annotation类将被javadoc 工具提取成文档, 即在生成文档时,可以看到该注解。
说明: 定义为Documented的注解必须设置Retention值为RUNTIME。
11.15.5 @Inherited¶
被它修饰的Annotation 将具有继承性.
如果某个类使用了被
@Inherited修饰的 Annotation, 则其子类将自动具有该注解