---
url: /doc/Java/ip1x3u8r/index.md
---
## 10.1 枚举

把具体的对象一一列举出来的类，就称为 枚举类（enumeration）

实现方法：

1. 自定义枚举
2. `enum` 关键字枚举

### 10.1.1 自定义枚举

1. 构造器私有化
2. 去掉 set 方法（可保留 get），防止属性被修改。因为枚举对象值通常为只读
3. 在类内部直接创建固定对象。使用 `final` + `static` 共同修饰，对象名通常全部大写。
4. 枚举对象按照需要可以有多个属性

### 10.1.2 `enum` 关键字

```java
enum Example {
 RED("小红", 10), BLUE("小蓝", 11), YELLOW; //这句话要放在前面，第三个是无参
 private String name;
 private int age;

 private Example(String name, int age) {
     this.name = name;
     this.age = age;
 }

}
```

1. 用关键字 `enum` 替代 `class`
2. 用 `常量名.(形参列表);` 代替创建对象（放在前面）。多个对象的场合，用 `,` 间隔。
3. 如果使用 `enum` 枚举，要求将常量对象写在前面

#### #10.1.2.1 使用细节

1. 当我们用 `enum` 关键字开发一个枚举类时，默认会继承 java.lang.Enum 类，而且是一个 `final` 类。

   这样，我们就能使用 Enum 中的相关方法。

   **也正因为如此，==`enum` 类不能继承其他类，亦不能被其它类继承==**

   不过，==`enum` 类和其他类一样，可以实现接口==。

2. 传统的 `public ststic final RED("小红", 10);` 简化为 `RED("小红", 10);`

3. 如果使用无参构造器创建枚举对象，则 实参列表 和 `( )` 都能省略

#### #10.1.2.2 `Enum` 类中的常用方法

* `valueOf`：将字符串转换成枚举对象。要求字符串必须是已有的常量名，否则报异常。
* `values`：返回一个数组 `Example[]`，其中包含定义的所有枚举对象
* `getDeclaringClass`：得到枚举常量所属的 `class`
* `name`：得到当前枚举常量的名称。建议优先用 `toString`
* `ordinal`：输出该枚举对象的次序/编号（从 0 开始编号。如上例 `BLUE.ordinal = 1`）
* `compareTo`：比较两个枚举常量的编号（调用常量编号 减去 传入常量编号）
* `clone`：==枚举类不能 `clone`，所以，这是一个只会抛出异常的方法==

### 10.1.3 Enumeration 接口

> Enumeration 接口中定义了一些方法，通过这些方法可以枚举（一次获得一个）对象集合中的元素。这种传统接口已被迭代器取代，虽然 Enumeration 还未被遗弃，但在现代代码中已经被很少使用了。尽管如此，它还是使用在诸如 Vector 和 Properties 这些传统类所定义的方法中，除此之外，还用在一些 API 类，并且在应用程序中也广泛被使用。 下表总结了一些 Enumeration 声明的方法：

| 1   | **boolean hasMoreElements( )** 测试此枚举是否包含更多的元素。                                |
| --- | -------------------------------------------------------------------------------------------- |
| 2   | **Object nextElement( )** 如果此枚举对象至少还有一个可提供的元素，则返回此枚举的下一个元素。 |

#### 实例

以下实例演示了 Enumeration 的使用：

```java
import java.util.Vector;
import java.util.Enumeration;

public class EnumerationTester {

   public static void main(String args[]) {
      Enumeration<String> days;
      Vector<String> dayNames = new Vector<String>();
      dayNames.add("Sunday");
      dayNames.add("Monday");
      dayNames.add("Tuesday");
      dayNames.add("Wednesday");
      dayNames.add("Thursday");
      dayNames.add("Friday");
      dayNames.add("Saturday");
      days = dayNames.elements();
      while (days.hasMoreElements()){
         System.out.println(days.nextElement());
      }
   }
}
```

```
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
```

## 10.2 注解

注解（Annotation）也被称为元数据（Metadata）。用于修饰 包、类、方法、属性、构造器、局部变量 等数据信息

和注释一样，注解不影响程序逻辑，但注解可以被编译或运行，相当于嵌入在代码中的补充信息

在 JavaSE 中，注解的使用目的比较简单，例如 标记过时的功能，忽略警告 等。在 JavaEE 中注解占据了更重要的角色，例如用于配置应用程序的任何切面，代替 JavaEE 旧版中所遗留的繁冗代码和 XML 配置等。

1. 使用 `@Annotation` 时要在前面增加 `@` 符号，并把该注解当成一个修饰符使用。用于修饰它支持的程序元素。

2. 三个基本的 `@Annotation`：

   * `@Override`：限定某个方法，是 重写 父类方法。该注解只能用于方法。如果你写了该注解，编译器会替你校验，看看是不是真的 重写 了父类方法。
   * `@Deprecated`：用于表示某个程序元素（类、方法等）已经过时
   * `@SuppressWarnings()`：抑制编辑器警告

3. 如果发现 `public @interface XXX{}` 这种东西，说明是定义了一个注解类 `XXX`。这里的 `@interface` 不代表接口（`interface`）。

### 10.2.1 `@Override`

1. `@Override` 表示指定重写父类的方法（从编译器层面验证），如果父类没有该方法，就报错
2. 不写该注解，重写依然构成重写
3. `@Override` 只能修饰方法，不能修饰其他 类、包、属性等
4. 查看 `@Override` 注解源码为 `@Target(ElementType.METHOD)` 说明只能修饰方法
5. `@Target` 是修饰注解的注解，称为 元注解

### 10.2.2 `@Deprecated`

1. `@Deprecated` 表示指定的某个程序元素（类、方法等）已过时

2. 不推荐使用，但仍能使用

3. 可以修饰方法、类、字段、包、参数

   `@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})`

4. `@Deprecated` 可以做到新旧版本的兼容和过度

### 10.2.3 `@SuppressWarnings()`

1. 当我们不想看到警告信息时，用 `@SuppressWarnings()`

   语法：`@SuppressWarnings({"..."})`

   在后面 `({"unused", "unchecked"})` 这样写入你希望抑制的信息，以下是所有可以输入的关键字

   | **关键字**               | **用途**                                             |
   | :----------------------- | :--------------------------------------------------- |
   | all                      | 抑制所有警告                                         |
   | boxing                   | 抑制与装箱/解装箱操作相关的警告                      |
   | cast                     | 抑制与强制转换操作相关的警告                         |
   | dep-ann                  | 抑制与已弃用注释相关的警告                           |
   | deprecation              | 抑制与弃用有关的警告                                 |
   | fallthrough              | 抑制与 switch 语句中丢失断点相关的警告               |
   | finally                  | 抑制不返回的 finally 块的相关警告                    |
   | hiding                   | 抑制与隐藏变量的局部变量相关的警告                   |
   | incomplete-switch        | 抑制与 switch 语句中缺少条目相关的警告（enum）       |
   | nls                      | 抑制与 非 nls 字符串字面值相关的警告                 |
   | null                     | 抑制相对于 null 分析的警告                           |
   | rawtypes                 | 在类参数上使用泛型时，抑制与非特定类型相关的警告     |
   | restriction              | 抑制与不推荐或禁止引用有关的警告                     |
   | serial                   | 抑制与可序列化类缺少 serialVersionUID 字段相关的警告 |
   | static-access            | 抑制与不正确的静态访问有关的警告                     |
   | synthetic-access         | 抑制与未优化的内部类访问相关的警告                   |
   | unchecked                | 抑制与未检查的操作相关的警告                         |
   | unqualified-field-access | 抑制与字段访问不合格相关的警告                       |
   | unused                   | 抑制与未使用代码相关的警告                           |

2. `@SuppressWarnings` 的范围与你放置的位置相关。

### 10.2.4 JDK 的元注解（了解即可）

> JDK 的 元注解 是用于修饰其他注解的注解

1. `@Rentention`：指定注解的作用范围，有三种范围 `SOURCE` `CLASS` `RUNTIME`

   `@Rentention` 的三种值：

   * `RententionPolicy.SOURCE`：编译器使用后，直接丢弃这种策略的注释
   * `RententionPolicy.CLASS`：编译器把注解记录在 class 文件中。当运行 Java 程序时， JVM 不会保留注释。这是默认值
   * `RententionPolicy.RUNTIME`：编译器把注解记录在 class 文件中。当运行 Java 程序时，JVM 会保留注解。程序可以通过反射获取该注解

2. `@Target`：指定注解的使用范围

   `@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})`

3. `@Documented`：指定该注解会不会在 Javadoc 体现

4. `@Inherited`：子类会继承父类注解
