枚举&注解

本文详细介绍了Java中的枚举类型及其使用,包括枚举的定义、枚举常量的分组以及如何实现接口。同时,文章还探讨了Java注解的基本概念,如内置注解、元注解、自定义注解的创建和使用,以及注解的生命周期和反射中的应用。枚举和注解是Java中重要的特性,对于代码管理和维护起到关键作用。
摘要由CSDN通过智能技术生成

枚举

在JDK1.5 之前,使用 public static final 定义常量,很难管理。 枚举,可以把相关的常量分组到一个枚举类型里,并且提供了比常量更多的方法。 用于定义有限数量的一组同类常量,例如: 四季: 春、夏、秋、冬

在枚举类型中定义的常量是该枚举类型的实例。

jdk1.5前

public class Level {
   public static final Level LOW=new Level(1);
   public static final Level Medium=new Level(50);
   public static final Level High=new Level(100);
   private  int value;
   private Level(int value) {
      this.value = value;
   }
   public int getValue() {
      return value;
   }
   public void setValue(int value) {
      this.value = value;
   }
}

定义格式

权限修饰符 enum 枚举名称 { 实例1,实例2,实例3,实例4; }

public enum Level {
    LOW, MEDIUM, HIGH;
}
public enum Level {
    LOW(30), MEDIUM(15), HIGH(7), URGENT(1);
    private int levelValue;
    private Level(int levelValue) {
       this.levelValue = levelValue;
    }
    public int getLevelValue() {
       return levelValue;
    }
}

实现接口的枚举类

所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。 每个枚举对象,都可以实现自己的抽象方法

interface LShow{
    void show();
}
public enum InterfaceLevel implements LShow{
    LOW(1){
        @Override
        public void show(){

        }
    },HIGH(10){
        @Override
        public void show(){

        }
    };
    private int levelValue;private InterfaceLevel(int levelValue) {
        this.levelValue = levelValue;
    }
    public int getLevelValue() {
        return levelValue;
    }
}

注意:

  • 枚举类默认继承的是java.lang.Enum类而不是Object类
  • 枚举类不能有子类,默认被final修饰
  • 只能有private构造方法 
  • 不能定义name属性,因为自带name属性
  • 不要为枚举类中的属性提供set方法,不符合枚举类设计初衷。 

注解

Annotation是一个接口,又称 Java 标注。注解是⼀种标记,使类,方法,成员,参数,接口,包等任何程序元素附加额外信息,帮助编译器和 JVM 完成⼀些特定功能。

和注释不同,Java 标注可以通过反射获取标注内容在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。(注解是通过反射获取的,可以通过 Class 对象的 isAnnotationPresent()方法判断它是否应 用了某个注解,再通过 getAnnotation()方法获取 Annotation 对象)它也支持自定义 Java 标注。

主要应用:

  • 编译格式检查
  • 反射中解析
  • 生成帮助文档
  • 跟踪代码依赖

重点:

  1. 概念
  2. 内置注解
  3. 自定义注解
  4. 反射中怎么获取注解内容

内置注解

  • @Override
  • @Deprecated
  • @SuppressWarnings
  • @FunctionalInterface
  • ...

元注解

作用在其他注解的注解

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。用于约束生命周期,值是 RetentionPolicy 枚举常量,包括 SOURCE 源码、CLASS 字节码和 RUNTIME 运行时。
  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在 class 文件中有效(即 class 保留)
  3. RUNTIME:在运行时有效(即运行时保留)
  • @Documented - 标记这些注解是否包含在用户文档中 javadoc。
  • @Target - 约束该注解作用位置,值是 ElementType 枚举常量,包括 METHOD 方法、VARIABLE 变量、TYPE 类/接口、PARAMETER 方法参数、CONSTRUCTORS 构造方法和 LOACL_VARIABLE 局部变量等。 
  • @Inherited - 标记这个注解是自动继承的(1. 子类会继承父类使用的注解中被@Inherited修饰的注解 2. 接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有 被@Inherited修饰 3. 类实现接口时不会继承任何接口中定义的注解)

每 1 个 Annotation 对象,都会有唯一的 RetentionPolicy 属性;有 1~n 个ElementType 属性.

当 Annotation 与某个 ElementType 关联 时,就意味着:Annotation有了某种用途。例如,若一个 Annotation 对象是 FIELD类型,则该 Annotation 只能用来修饰字段。

package java.lang.annotation;
public enum ElementType {
TYPE, /* 类、接口(包括注释类型)或枚举声明 */
FIELD, /* 字段声明(包括枚举常量) */
METHOD, /* 方法声明 */
PARAMETER, /* 参数声明 */
CONSTRUCTOR, /* 构造方法声明 */
LOCAL_VARIABLE, /* 局部变量声明 */
ANNOTATION_TYPE, /* 注释类型声明 */
PACKAGE /* 包声明 */
}

 "每 1 个 Annotation" 都与 "1 个 RetentionPolicy" 关联。

  • 若 Annotation 的类型为 SOURCE,则意味着:Annotation 仅存在于编译器处理期间,编译器 处理完之后,该 Annotation 就没用了。 例如," @Override" 标志就是一个 Annotation。当它修 饰一个方法的时候,就意味着该方法覆盖父类的方法;并且在编译期间会进行语法检查!编译器处 理完后,"@Override" 就没有任何作用了。编译器可利用注解来探测错误和警告信息
  • 若 Annotation 的类型为 CLASS,则意味着:编译器将 Annotation 存储于类对应的 .class 文件 中,它是 Annotation 的默认行为。软件工具可以利用注解信息来生成代码、html 文档或做其它相应处理;
  • 若 Annotation 的类型为 RUNTIME,则意味着:编译器将 Annotation 存储于 class 文件中,并 且可由JVM读入。程序运行时可利用注解提取代码
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该
Annotation信息了 */
CLASS, /* 编译器将Annotation存储于类对应的.class文件中。默认行为 */
RUNTIME /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}

自定义注解

  • 用@Interface来声明注解(要使其正常工作,需要使用元注解)
  • 定义的注解,自动继承了java.lang,annotation.Annotation接口
  • 注解中的每一个方法,实际是声明的注解配置参数 (方法的名称就是 配置参数的名称 方法的返回值类型,就是配置参数的类型。只能是:基本类型/Class/String/enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value
  • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串、0作为默认值。 
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
参数类型 参数名() default 默认值;
}

上面的作用是定义一个 Annotation,我们可以在代码中通过 "@MyAnnotation" 来使用它。 @Documented, @Target, @Retention, @interface 都是来修饰 MyAnnotation 的。 

(01) @interface 使用 @interface 定义注解时,表示它实现了 java.lang.annotation.Annotation 接口,即该注解就是 一个Annotation。 定义 Annotation 时,@interface 是必须的。 (它和通常的 implemented 实现接口的方法不同。Annotation 接口的实现细节都由编译器完 成。通过 @interface 定义注解后,该注解不能继承其他的注解或接口)

(02) @Documented 类和方法的 Annotation 在缺省情况下是不出现在 javadoc 中的。如果使用 @Documented 修饰该 Annotation,则表示它可以出现在 javadoc 中。 定义 Annotation 时,@Documented 可有可无;若没有定义,则 Annotation 不会出现在 javadoc 中。

(03) @Target(ElementType.TYPE) ,ElementType 是 Annotation 的类型属性。而 @Target 的作用,就是来指定 Annotation 的类型属性。 @Target(ElementType.TYPE) 的意思就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味 着,MyAnnotation是来修饰"类、接口(包括注释类型)或枚举声明"的注解。 定义 Annotation 时,@Target 可有可无。若有 @Target,则该 Annotation 只能用于它所指定的地 方;若没有 @Target,则该 Annotation 可以用于任何地方。

(04) @Retention(RetentionPolicy.RUNTIME) ,RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的作用,就是指定 Annotation 的策略属性。 @Retention(RetentionPolicy.RUNTIME) 的意思就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 信息保留在 .class 文件中,并且 能被JVM读取。 定义 Annotation 时,@Retention 可有可无。若没有 @Retention,则默认是 RetentionPolicy.CLASS。 

反射帮助程序员快速构造自定义注解处理器。

public class AnnotationDemo {
    @Provider(id = 1, name = "名字", email = "邮件")
    private String provider;
    public void setProvider(String appleProvider) {
        this.provider = appleProvider;
    }
    public String getProvider() {
        return provider;
    }
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Provider {
    public int id() default 0;
    public String name() default "";
    public String email() default "";
}
/*注解处理器*/
 class Util {
    public static void getInfo(Class<?> clazz) {
        String provider = "";
        Field[] fields = clazz.getDeclaredFields();//通过反射获取处理注解
        for (Field field : fields) {
            if (field.isAnnotationPresent(Provider.class)) {
                Provider p = (Provider) field.getAnnotation(Provider.class);
                //注解信息处理
                provider = " 编号:" + p.id() + " 名称:"
                        + p.name() + " 邮件:"+ p.email();
                System.out.println(provider);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值