跳转至

11枚举和注解

11.1枚举

2022年6月9日

12:43

  1. 引入: 为什么需要枚举

    当对于一个类, 我们需要固定的几个对象(例如一个类Season,我们只能有四个对象(春夏秋冬),而不能有额外的对象)

  2. 枚举: 一组常量的集合 (可以理解为一种特殊的类, 里面只包含一组有限的特定的对象)

  3. 枚举的实现方法:

自定义类实现枚举

注意点: 构造器设为private防止调用, 去掉set方法防止修改, 在类构建固定对象

final class Season {

private String name;

private String desc; //描述

//定义四个固定对象

public static final Season SPRING = new Season("春", "温暖");

public static final Season SUMMER = new Season("夏", "炎热");

public static final Season AUTUMN = new Season("秋", "凉爽");

public static final Season WINTER = 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='" + desc + ''' +

'}';

}

}
enum关键字实现枚举
enum Season {

  - //参数名(实参列表)来定义枚举量
  - //多个常量使用","来连接
  - //如果使用无参构造器构建对象的话, 可以省略()
  - //使用enum时应该将定义的常量写在前面
  - //其余部分相同
    SPRING("春", "温暖"), SUMMER("夏", "炎热"),
    AUTUMN("秋", "凉爽"), WINTER("冬", "寒冷");
    private String name;
    private 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 + ''' +
            '}';
    }
}
  1. 使用enum关键字实现枚举的注意事项

    1. 使用enum关键字建立一个枚举类时, 默认会继承Enum类, 并且将自己定义为final类

    2. 可以将普通的

      `public static final Season SPRING = new Season("春", "温暖");`
      
      简化为`SPRING("春", "温暖");`
      
      但必须知道调用的是哪个构造器
      
    3. 使用无参构造器创建枚举对象是,可以省略()和实参列表

    4. 多个枚举对象用","连接

    5. 枚举对象必须放在枚举类行首

  2. enum类常用方法

    说明:因为所有enum类隐式继承Enum类, 所以可以使用Enum类方法

protected Object clone() 抛出 CloneNotSupportedException。 枚举类型不能被克隆
int compareTo(E o) 比较此枚举与指定对象的顺序。
boolean equals(Object other) 当指定对象等于此枚举常量时,返回 true。 可以直接使用"=="来判断是否相等
protected void finalize() 枚举类不能有 finalize 方法。
Class<E> getDeclaringClass() 返回与此枚举常量的枚举类型相对应的 Class 对象。 用于判断两个枚举常量是否属于同一个枚举类型
int hashCode() 返回枚举常量的哈希码。(覆盖Object的hashCode)
String name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。 建议优先使用toString()方法
int ordinal() 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零(0,1,2,3….))。
String toString() 返回枚举常量的名称,它包含在声明中。 可以重写
static Enum\> T valueOf(Class enumType, String name) 返回带指定名称的指定枚举类型的枚举常量。

values:返回当前枚举类中的所有常量

来自 <https://itmyhome.com/java-api/java/lang/Enum.html>

  1. enum实现接口

    1. enum隐式继承Enum, 不能继承其他类(java只能单继承), 因此可以使用接口来完成功能

    2. 形式:与类相同

      enum 类名 implements 接口1(,接口2,接口3) {
      }
      

11.2注解

2022年6月14日

17:12

1. 什么是注解

  1. jdk 5.0 新增的功能

  2. 注解(Annotation)也被称为元数据(Metadata), 用于修饰解释 包、类、方法、属性、构造器、局部变量等数据的信息, 这些信息被保存在Annotation的 name = value 对中。

  3. Annotation的作用:

    • 和注释一样, 注解不影响程序逻辑, 但注解可以被编译或者运行, 相当于嵌入代码中的补充信息
    • 注解可以被其他程序(如:编译器等)读取
    • JavaSe中, 注解作用简单, 例如标记过时的功能, 忽略警告等

      JavaEE中, 用于配置应用程序的任何切面, 代替JavaEE旧版中遗留的繁冗代码和XML配置等

  4. Annotation'的格式:

    • 注解是以"@注解名"在代码中存在的, 还可以添加一些参数值, 如:@SuppressWarning(value = "unchecked")
  5. Annotation在哪里使用:

    • 可以附加在package, class, method, field等上面, 相当于为它们添加了额外的辅助信息, 我们可以通过反射机制实现对这些元数据的访问
  6. 框架 = 注解 + 反射机制 + 设计模式

2. 基本的Annotation介绍

  1. @Override: 限定某个方法是重写父类方法 (只能用于方法)

    1. 编译器会检查方法是否真的重写了父类方法, 否则编译错误

    2. 如果不写@Override注解依然构成重写

    3. @Override只能修饰方法

    4. 源码

      @Target(ElementType.METHOD)
      @Retention(RetentionPolicy.SOURCE)
      public @interface Override {
      }
      
  2. @Deprecated: 表示某个程序元素(类/方法)已过时

    1. 表示不在推荐使用, 但是仍然可以使用

    2. 可以修饰方法, 类, 字段, 包, 参数等

    3. @Deprecated可以作为版本升级过渡使用

    4. 源码

      @Documented
      @Retention(RetentionPolicy.RUNTIME)
      @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
      public @interface Deprecated {
      }
      
  3. @SuppressWarnings: 抑制编译器警告

    1. 使用: @SuppressWarnings({""}) 内部写入希望抑制的警告信息

      关键字 用途
      all 抑制所有警告
      boxing 抑制装箱、拆箱操作时候的警告
      cast 抑制映射相关的警告
      dep-ann 抑制启用注释的警告
      deprecation 抑制过期方法警告
      fallthrough 抑制在 switch 中缺失 breaks 的警告
      finally 抑制 finally 模块没有返回的警告
      hiding 抑制相对于隐藏变量的局部变量的警告
      incomplete-switch 忽略不完整的 switch 语句
      nls 忽略非 nls 格式的字符
      null 忽略对 null 的操作
      rawtypes 使用 generics 时忽略没有指定相应的类型
      restriction 抑制禁止使用劝阻或禁止引用的警告
      serial 忽略在 serializable 类中没有声明 serialVersionUID 变量
      static-access 抑制不正确的静态访问方式警告
      synthetic-access 抑制子类没有按最优方法访问内部类的警告
      unchecked 抑制没有进行类型检查操作的警告
      unqualified-field-access 抑制没有权限访问的域的警告
      unused 抑制没被使用过的代码的警告
    2. 作用范围与放置位置有关, 可以放置于具体的==语句, 方法, 类==

    3. 源码

      @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
      @Retention(RetentionPolicy.SOURCE)
      public @interface SuppressWarnings {
          /**
           * The set of warnings that are to be suppressed by the compiler in the
           * annotated element.  Duplicate names are permitted.  The second and
           * successive occurrences of a name are ignored.  The presence of
           * unrecognized warning names is <i>not</i> an error: Compilers must
           * ignore any warning names they do not recognize.  They are, however,
           * free to emit a warning if an annotation contains an unrecognized
           * warning name.
           *
           * <p> The string {@code "unchecked"} is used to suppress
           * unchecked warnings. Compiler vendors should document the
           * additional warning names they support in conjunction with this
           * annotation type. They are encouraged to cooperate to ensure
           * that the same names work across multiple compilers.
           * @return the set of warnings to be suppressed
           */
          String[] value();
      }
      

3. 注解的使用示例

使用 Annotation时要在其前面增加 @ 符号,并把该 Annotation当成个修饰符使用。用于修饰它支持的程序元素

例一:生成文档相关的注解
  • @author 标明开发该类模块的作者,多个作者之间使用,分割 @version 标明该类模块的版本;
  • @see 参考转向,也就是相关主题;
  • @since 从哪个版本开始增加的;
  • @param 对方法中某参数的说明,如果没有参数就不能写 @return 对方法返回值的说明,如果方法的返回值类型是 void 就不能写 @exception 对方法可能抛出的异常进行说明,如果方法没有用 throws 显式抛出的异常就不能写;
  • 其中 @param@return@exception 这三个标记都是只用于方法的。
  • @param 的格式要求:@param 形参名形参类型形参说明;
  • @return 的格式要求:@return 返回值类型返回值说明;
  • @exception 的格式要求:@exception 异常类型异常说明;
  • @param@exception 可以并列多个;

代码示例:

/**
 * @author bruce
 * @project_name JavaSenior
 * @package_name com.bruce.java
 * @create 2020-04-26 10:58
 */
public class AnnotationTest {
    /**
     *程序的主方法
     * @param args 传入命令行参数
     */
    public static void main(String[] args) {

    }

    /**
     * 求圆形面积
     * @param radius 所求面积的半径
     * @return 面积值
     */
    public static double getArea(double radius){
        return Math.PI * radius * radius;
    }
}
例二:在编译时进行格式检查(JDK内置的基本注解)
  • @Override: 限定重写父类方法, 该注解只能用于方法;
  • @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的择;
  • @SuppressWarnings: 抑制编译器警告;

代码示例:

public class AnnotationTest{
    public static void mian (String [] args){
        @SuppressWarning("unused")
        int a = 0;
    }
    @Deprecated
    public void print(){
        System.out.print("过时的方法");
    }
    @Override
    public String toString(){
        return "重写的toString方法";
    }
}
例三:跟踪代码依赖性,实现替代配置文件功能

在使用Spring框架时会大量用到注解驱动开发。

4. 如何自定义注解

参照 @SuppressWarnings 定义

  1. 注解声明为:访问权限 @interface 注解名 {}
  2. 内部定义成员,通常使用value表示
  3. 可以指定成员的默认值,使用default定义
  4. 如果自定义注解没成员,表明是一个标识作用。
4.1 说明
  • 如果注解有成员,在使用注解时,需要指明成员的值。
  • 自定义注解必须配上注解的信息处理流程(使用反射)才意义。
  • 自定义注解通过都会指明两个元注解:@Retention@Target
4.2 代码举例:
@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER,TYPE_USE})
public @interface MyAnnotation {
    String value() default "hello";
}

5. 元注解:

  1. 总述:

    1. 元注解: 用于修饰其他注解 (源码中使用) <仅了解>

    2. 分类

      * Retention : 指定注解的作用范围,有三种 SOURCE, CLASS, RUNTIME

      * Target : 指定注解可以在哪些地方使用

      * Documented : 指定该注解是否会在javadoc 体现

      * Inherited : 子类会继承父类注解

  2. @Retention

    1. 说明: 只能用于修饰一个Annotation 定义, 用于指定该Annotation 可以保留多长时间, @Rentention 包含一个RetentionPolicy类型的成员变量

    2. 使用@Rentention 时必须为该value 成员变量指定值:

      @Retention 的三种值

      1. RetentionPolicy.SOURCE: 编译器使用后,直接丢弃这种策略的注释

      2. RetentionPolicy.CLASS: 编译器将把注解记录在class 文件中. 当运行Java 程序时, JVM 不会保留注解。这是默认值

      3. RetentionPolicy.RUNTIME:编译器将把注解记录在class 文件中. 当运行Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注解

    3. 源码

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
  1. @Target

    1. 用于修饰Annotation定义, 用于指定被修饰的Annotation用于修饰那些程序元素

    2. Target也包含一个value成员变量

    3. 源码:

      @Documented
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.ANNOTATION_TYPE)
      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();
      }
      
  2. @Documented

    1. 用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档, 即在生成文档时, 可以看到该注解

    2. 源码

      @Documented
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.ANNOTATION_TYPE)
      public @interface Documented {
      }
      
  3. @Inherited

    1. 被它修饰的Annotation将具有继承性, 如果某个类使用了被@Inherited修饰的Annotation, 则其子类将自动具有该注解 2. 说明: 实际应用中, 使用较少, 仅了解

6. 如何获取注解信息:

通过反射来进行获取、调用。

前提:要求此注解的元注解Retention中声明的生命周期状态为:RUNTIME.

7. JDK 8.0中注解的新特性:

可重复注解、类型注解

6.1 可重复注解:

① 在MyAnnotation上声明 @Repeatable,成员值为 MyAnnotations.class

② MyAnnotation的Target和Retention等元注解与MyAnnotations相同。

6.2 类型注解:

ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如:泛型声明。)

ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。