7.1 枚举类

枚举类的对象只有有限个确定数值,如星期、性别、季节等。构造器必须使用private,所有实例必须在枚举类中显式列出,系统将自动为其添加public static final修饰,且必须在枚举类的第一行声明枚举类对象。

switch表达式中可使用enmu定义的枚举类对象作为表达式, case 子句可以直接使用枚举值的名字。

  1. public enum SeasonEnum {
  2. SPRING("春天","春风又绿江南岸"),
  3. SUMMER("夏天","映日荷花别样红"),
  4. AUTUMN("秋天","秋水共长天一色"),
  5. WINTER("冬天","窗含西岭千秋雪"); // 注意这里的符号
  6. private final String seasonName;
  7. private final String seasonDesc;
  8. private SeasonEnum(String seasonName, String seasonDesc) {
  9. this.seasonName = seasonName;
  10. this.seasonDesc = seasonDesc;
  11. }
  12. public String getSeasonName() {
  13. return seasonName;
  14. }
  15. public String getSeasonDesc() {
  16. return seasonDesc;
  17. }
  18. }
  1. // 例子
  2. SeasonEnum summer = SeasonEnum.SUMMER;
  3. SeasonEnum[] values = SeasonEnum.values(); // 返回枚举类型的对象数组

7.2 注解

注解(Annotation)是代码里的特殊标记,可在编译、 类加载、 运行时被读取, 并根据注解类型执行相应处理。通过使用注解,程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息,代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或部署。

7.2.1 注解的使用情景

注解通常用于标记过时功能,忽略警告,配置应用程序(如XML配置)等。未来的开发模式都是基于注解的,一定程度上可以说:框架 = 注解 + 反射 + 设计模式。

示例一:生成文档相关的注解

  1. @author
  2. @version
  3. @see // 相关主题
  4. @since // 从哪个版本开始增加的
  5. @Description // 功能描述
  6. @date
  7. // 仅用于方法的标记,@param和@exception可以并列多个
  8. @param // 对方法中某参数的说明
  9. @return // 对方法返回值的说明
  10. @exception // 对方法可能抛出的异常进行说明
  11. @param 形参名 形参类型 形参说明
  12. @return 返回值类型 返回值说明
  13. @exception 异常类型 异常说明
  1. package com.annotation.javadoc;
  2. /**
  3. * @author shkstart
  4. * @version 1.0
  5. * @see Math.java
  6. */
  7. public class JavadocTest {
  8. /**
  9. * 程序的主方法,程序的入口
  10. * @param args String[] 命令行参数
  11. */
  12. public static void main(String[] args) {
  13. }
  14. /**
  15. * 求圆面积的方法
  16. * @param radius double 半径值
  17. * @return double 圆的面积
  18. */
  19. public static double getArea(double radius){
  20. return Math.PI * radius * radius;
  21. }
  22. }

示例二:在编译时进行格式检查(JDK内置的三个基本注解)

  1. @Override // (凌驾、覆盖)标明是重写方法,不写也可能为重写方法
  2. @Deprecated // (过时)表明不推荐使用
  3. @SuppressWarnings // 抑制编译器警告
  1. package com.annotation.javadoc;
  2. public class AnnotationTest{
  3. public static void main(String[] args) {
  4. @SuppressWarnings("unused")
  5. int a = 10;
  6. }
  7. @Deprecated
  8. public void print(){
  9. System.out.println("过时的方法");
  10. }
  11. @Override
  12. public String toString() {
  13. return "重写的toString方法()";
  14. }
  15. }

示例三:跟踪代码依赖性,实现替代配置文件功能

在Java Web中会用到Servlet接口,通过注解则无需在web.xml中进行Servlet部署

7.2.2 自定义注解

自定义注解使用 @interface 关键字,其自动继承java.lang.annotation.Annotation接口,注解的成员变量以无参数方法声明,我们称为配置参数。类型只能是八种基本数据类型、String、Class、Enum、Annotation。

可以在定义注解的成员变量时为其指定初始值,指定成员变量的初始值使用 default,如果只有一个参数成员,建议使用参数名value。如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是“参数名 = 参数值”,如果只有一个参数成员,且名称为value,可以省略“value=” 。

没有成员定义的注解称为标记; 包含成员变量的注解称为元数据 Annotation。

  1. // 例子1 成员变量无参
  2. public @interface MyAnnotation{
  3. String value(); // 成员变量以无参方法声明,定义名字和类型
  4. }
  5. @MyAnnotation( value = "hello") // 注解无默认配置参数,必须指定参数
  6. @MyAnnotation("hello") // 仅一个变量且名称为value,省略变量名
  7. // 例子2 成员变量有参数
  8. public @interface MyAnnotation{
  9. String value() default "hello"; // 成员变量以无参方法声明,定义名字和类型并指定初始值
  10. }
  11. @MyAnnotation( value = "hi")
  12. @MyAnnotation
  13. // 例子三 无成员变量作为特殊标识
  14. public @interface MyAnnotation{
  15. }
  16. @MyAnnotation

7.2.3 JDK中的元注解

元注解是对现有的注解进行解释说明的注解。

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.SOURCE)
  3. public @interface Override{
  4. }
  1. Retention(留存):指定注解的生命周期,其包含一个 RetentionPolicy 类型的成员变量:
    • RetentionPolicy.SOURCE:在源文件中有效,在class文件中不再加载
    • RetentionPolicy.CLASS:在class文件中有效,不会将此注解加载到内存。 这是默认值
    • RetentionPolicy.RUNTIME:在运行时有效,当运行程序时, JVM会保留注释。程序可以通过反射获取该注释。
  2. Target(目标):指定注解能用于修饰哪些程序元素。可用,进行多种修饰:

    1. CONSTRUCTOR:用于描述构造器
    2. PACKAGE:用于描述包
    3. FIELD:用于描述域
    4. PARAMETER:用于描述参数
    5. LOCAL_VARIABLE:用于描述局部变量
    6. TYPE:用于描述类、接口(包括注解类型)或enum声明
    7. METHOD:用于描述方法
  3. Documented:指定注解类将被javadoc工具提取成文档。默认情况下,javadoc是不包括注解的。 定义为Documented的注解必须设置Retention值为RUNTIME。

  4. Inherited:修饰的注解将具有继承性。如果某个类使用了其修饰的 Annotation, 则其子类将自动具有该注解。

    7.2.4 JDK8中注解的新特性

  5. 可重复注解: ```java // JDK8前声明重复注解 public @interface MyAnnotations{ MyAnnotation[] value(); } @MyAnnotations({@MyAnnotation(value=”hi”),@MyAnnotation(value=”hello”)})

// JDK8写法 @Repeatable(MyAnnotations.class) // 此时两种注解声明周期应当相同,修饰类型也应当相同,即Retention、Target等元注解必须相同 public @interface MyAnnotation{ String value();
} public @interface MyAnnotations{ MyAnnotation[] value(); }

  1. 2. 用于类型的注解:在Java 8之前,注解只能在声明的地方所使用,Java8开始,注解可以应用在任何地方。
  2. ```java
  3. /* jdk8新加入的Target枚举值
  4. * TYPE_PARAMETER:表示该注解能写在类型变量的声明语句中(如:泛型声明)
  5. * TYPE_USE:表示该注解能写在使用类型的任何语句中。
  6. */
  7. // 例子1
  8. public class TestTypeDefine<@TypeDefine() U> {
  9. private U u;
  10. public <@TypeDefine() T> void test(T t){
  11. }
  12. }
  13. @Target({ElementType.TYPE_PARAMETER})
  14. @interface TypeDefine{
  15. }
  16. // 例子2
  17. @MyAnnotation
  18. public class AnnotationTest<U> {
  19. @MyAnnotation
  20. private String name;
  21. public static void main(String[] args) {
  22. AnnotationTest<@MyAnnotation String> t = null;
  23. int a = (@MyAnnotation int) 2L;
  24. }
  25. public static <@MyAnnotation T> void method(T t) {
  26. }
  27. public static void test(@MyAnnotation String arg) throws @MyAnnotation Exception {
  28. }
  29. }
  30. @Target(ElementType.TYPE_USE)
  31. @interface MyAnnotation {
  32. }