JAVA篇06 —— enum&Annotation

 欢迎来到我的主页:【一只认真写代码的程序猿

本篇文章收录于专栏【小小爪哇

如果这篇文章对你有帮助,希望点赞收藏加关注啦~

目录

1 自定义实现枚举

2 关键字enum

3 values() ordinal() valueOf()

4 enum常用方法示例

5 enum实现接口

6 注解

6.1 @Override

6.2 @Deprecated

6.3 @SuppressWarnings

7 元注解

7.1 @Retention

7.2 @Target

7.3 @Documented

7.4 @Inherited


设计一个季节类,需要去分别new四次很麻烦。我们发现:季节的值是有限的几个值(spring, summer, autumn, winter)并且是只读,不需要修改。枚举属于一种特殊的类, 里面只包含一组有限的特定的对象。

  1. 不需要提供setXxx 方法,因为枚举对象值通常为只读。
  2. 对枚举对象/属性使用 final + static 共同修饰,实现底层优化。
  3. 枚举对象名通常使用全部大写,常量的命名规范。
  4. 枚举对象根据需要,也可以有多个属性 。

1 自定义实现枚举

1) 构造器私有化

2) 本类内部创建一组对象[四个 春夏秋冬]

3) 对外暴露对象(通过为对象添加 public final static 修饰符)

4) 可以提供 get 方法, 但是不要提供 set

package Enumeration;

/**
 * @ClassName Season
 * @Description
 * @Date 2024/11/27 20:17
 * @Version V1.0
 */
public class Season {
    public static void main(String[] args) {
        System.out.println(Seasons.AUTUMN);
        System.out.println(Seasons.SPRING);
    }
}

class Seasons {//类
    //定义了四个对象, 固定.
    public static final Seasons SPRING = new Seasons("春天", "温暖");
    public static final Seasons WINTER = new Seasons("冬天", "寒冷");
    public static final Seasons AUTUMN = new Seasons("秋天", "凉爽");
    public static final Seasons SUMMER = new Seasons("夏天", "炎热");
    private String name;
    private String desc;//描述

    //1. 将构造器私有化,目的防止 直接 new
    //2. 去掉 setXxx 方法, 防止属性被修改
    //3. 在 Season 内部, 直接创建固定的对象
    //4. 优化, 可以加入 final 修饰符
    private Seasons(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 + '\'' +
                '}';
    }
}

2 关键字enum

package Enumeration;

/**
 * @ClassName Season
 * @Description
 * @Author 聂宇旋
 * @Date 2024/11/27 20:17
 * @Version V1.0
 */
public class Season {
    public static void main(String[] args) {
        System.out.println(Seasons2.AUTUMN);
        System.out.println(Seasons2.SPRING);
    }
}

enum Seasons2{
    SPRING("春天", "温暖"),
    WINTER("冬天", "寒冷"),
    AUTUMN("秋天", "凉爽"),
    SUMMER("夏天", "炎热"),
    ;
    private String name;
    private String dec;
    private Seasons2(){}
    private Seasons2(String name,String dec){
        this.name = name;
        this.dec=dec;
    }

    public String getName() {
        return name;
    }

    public String getDec() {
        return dec;
    }

    @Override
    public String toString() {
        return "Season{"+
                "name="+name
                +"description="+dec
                +"}";
    }
}

3 values() ordinal() valueOf()

enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。

values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量.
  • 当我们使用 enum 关键字开发一个枚举类时, 默认会继承 Enum 类, 而且是一个 final 类。
  • 传统的 public static final Season2 SPRING = new Season2("春天", "温暖"); 简化成 SPRING("春天", "温暖")。
  • 如果使用无参构造器 创建 枚举对象, 则实参列表和小括号都可以省略(代码如下)
enum Color{ 
    RED, GREEN, BLUE; 
} 
public class Test{ 
    public static void main(String[] args){ 
        // 调用 values() 
        Color[] arr = Color.values(); 
  
        // 迭代枚举
        for (Color col : arr) { 
            // 查看索引
            System.out.println(col + " at index " + col.ordinal()); 
        } 
  
        // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException 
        System.out.println(Color.valueOf("RED")); 
        // System.out.println(Color.valueOf("WHITE")); 
    } 
}

4 enum常用方法示例

正如前面所说,enum会隐式继承Enum。

public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
}
  1. toString:Enum 类已经重写过了, 返回的是当前对象名,子类可以重写该方法, 用于返回对象的属性信息
  2. name: 返回当前对象名(常量名) , 子类中不能重写
  3. ordinal: 返回当前对象的位置号, 默认从 0 开始 
  4. values: 返回当前枚举类中所有的常量
  5. valueOf: 将字符串转换成枚举对象, 要求字符串必须为已有的常量名, 否则报异常
  6. compareTo: 比较两个枚举常量, 比较的就是编号
package Enumeration;

enum Seasons2 {
    SPRING("春天", "温暖"),
    WINTER("冬天", "寒冷"),
    AUTUMN("秋天", "凉爽"),
    SUMMER("夏天", "炎热"),
    ;
    private String name;
    private String dec;

    private Seasons2() {
    }

    private Seasons2(String name, String dec) {
        this.name = name;
        this.dec = dec;
    }

    public String getName() {
        return name;
    }

    public String getDec() {
        return dec;
    }

    @Override
    public String toString() {
        return "Season{" +
                "name=" + name
                + "description=" + dec
                + "}";
    }
}

/**
 * @ClassName Season
 * @Description
 * @Author 聂宇旋
 * @Date 2024/11/27 20:17
 * @Version V1.0
 */
public class Season {
    public static void main(String[] args) {
        Seasons2 winter = Seasons2.WINTER;
        System.out.println(winter.name());//输出名字WINTER
        System.out.println(winter.ordinal());//输出下标,与数组类似,输出1
        Seasons2[] values = Seasons2.values();//获取所有值,放入values数组
        for (Seasons2 season : values) {//增强for来遍历输出
            System.out.println(season);
        }
        Seasons2 autumn1 = Seasons2.AUTUMN;
        Seasons2 autumn = Seasons2.valueOf("AUTUMN");//根据字符串查找,且String必须在枚举中否则报错
        System.out.println("autumn=" + autumn);
        System.out.println(autumn);
        System.out.println(autumn == autumn1);//True
    }
}

5 enum实现接口

package Enumeration;

/**
 * @ClassName enumImpl
 * @Description 枚举类实现接口
 * @Date 2024/11/28 9:08
 * @Version V1.0
 */
public class enumImpl {
    public static void main(String[] args) {
        Music.CLASSICMUSIC.play();
    }
}
interface IPlay{
    void play();
}
enum Music implements IPlay{
    CLASSICMUSIC,
    POPMUSIC,
    ;

    @Override
    public void play() {
        System.out.println("音乐...");
    }
}

6 注解

  1. 注解(Annotation)也被称为元数据(Metadata), 用于修饰解释 包、 类、 方法、 属性、 构造器、 局部变量等数据信息。
  2. 和注释一样, 注解不影响程序逻辑, 但注解可以被编译或运行, 相当于嵌入在代码中的补充信息。
  3. 在 JavaSE 中, 注解的使用目的比较简单, 例如标记过时的功能, 忽略警告等。 在 JavaEE 中注解占据了更重要的角色, 例如用来配置应用程序的任何切面, 代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。

6.1 @Override

@Interface表示一个“注解类”,只能重写方法(Target里是METHOD),并且会检查是否真的重写了,如果没有重写则报错。Target是修饰注解的注解,称为“元注解”。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

6.2 @Deprecated

用于表示某个程序元素(类, 方法等)已过时。可以做版本升级过渡使用。如果继续使用的话编译器会warning来提醒。

package Enumeration;

/**
 * @ClassName DeprecatedTest
 * @Description @Deprecated注解的使用
 * 1. @Deprecated 修饰某个元素, 表示该元素已经过时
 * 2. 即不在推荐使用, 但是仍然可以使用
 * 3. 查看 @Deprecated 注解类的源码
 * 4. 可以修饰方法, 类, 字段, 包, 参数 等等
 * 5. @Deprecated 可以做版本升级过渡使用
 * @Date 2024/11/28 9:18
 * @Version V1.0
 */

/*
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
*/

public class DeprecatedTest {
    public static void main(String[] args) {
        A a = new A();
        a.hi();
        System.out.println(a.n1);
    }
}

@Deprecated
class A {
    @Deprecated
    public int n1 = 10;

    @Deprecated
    public void hi() {
    }
}

6.3 @SuppressWarnings

不用背,IDE中可以看提示,做产品迭代使用的注解。

package Enumeration;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName SuppressWarnings_
 * @Description 当我们不希望看到这些警告的时候, 可以使用 SuppressWarnings 注解来抑制警告信息
 * 在{""} 中, 可以写入你希望抑制(不显示)警告信息
 * 可以指定的警告类型有
 * 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, 抑制与未用的程式码及停用的程式码相关的警告
 * @Author 聂宇旋
 * @Date 20241128 9:25
 * @Version V1.0
 */

// 关于 SuppressWarnings 作用范围是和你放置的位置相关
// 比如 @SuppressWarnings 放置在 main 方法, 那么抑制警告的范围就是 main
// 通常我们可以放置具体的语句, 方法, 类
//(1) 放置的位置就是 TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE
//(2) 该注解类有数组 String[] values() 设置一个数组比如 {"rawtypes", "unchecked", "unused"}
@SuppressWarnings({"rawtypes", "unchecked", "unused"})
public class SuppressWarnings_ {
    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));
    }
}
/*
源码如下:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}*/

7 元注解

使用不多,了解即可,方便看源码的时候知道他在干啥。

  • Retention //指定注解的作用范围, 三种 SOURCE,CLASS,RUNTIME
  • Target // 指定注解可以在哪些地方使用
  • Documented //指定该注解是否会在 javadoc 体现
  • Inherited //子类会继承父类注解

7.1 @Retention

只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留多长时间 @Rentention 包含一个 RetentionPolicy类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值。

@Retention 的三种值:

  1. RetentionPolicy.SOURCE: 编译器使用后, 直接丢弃这种策略的注
  2. RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解。 这是默认值。
  3. RetentionPolicy.RUNTIME:编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注解
  4. 案例:Override中用了
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

//解释:Override的作用域在SOURCE,即编译时生效,不会写入到class文件
//也不会在Runtime时生效

7.2 @Target

用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素,@Target 也包含一个名为 value 的成员变量。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
//可以修饰方法, 类, 字段, 包, 参数 等等
public @interface Deprecated {
}

Target源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)//作用范围是Runtime
@Target(ElementType.ANNOTATION_TYPE)//AnnotationType就说明Target只能修饰注解
public @interface Target {//说明它是注解
    /**
     * Returns an array of the kinds of elements an annotation interface
     * can be applied to.
     * @return an array of the kinds of elements an annotation interface
     * can be applied to
     */
    ElementType[] value();//看elementType的取值
}

7.3 @Documented

生成文档用的,被Document注解的注解,在javadoc提取成文档后,在文档中可以看到这个注解。

所以,定义为Document的注解必须把Retention设置为Runtime。举例如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
//可以修饰方法, 类, 字段, 包, 参数 等等
public @interface Deprecated {
}

Document源码(注释由GPT生成):

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
/*
1. `@Documented`:这是一个元注解(meta-annotation)
意味着它被用来注解其他注解。`@Documented` 注解本身被
用来指示被它标记的注解应该被 javadoc 工具包含在生成的文档中。

2. `@Retention(RetentionPolicy.RUNTIME)`:这是另一个元注解,
`@Retention` 指定了注解的保留策略。`RetentionPolicy.RUNTIME` 
表示这个注解应该在运行时保留,这意味着它可以通过反射(Reflection)被检测到。

3. `@Target(ElementType.ANNOTATION_TYPE)`:这是第三个元注解,
`@Target` 指定了注解可以应用的Java元素类型。
`ElementType.ANNOTATION_TYPE` 表示这个注解只能用于其他注解类型。

4. `public @interface Documented { }`:这是定义注解的声明。
`@interface` 是用来声明注解的关键字。`Documented` 是注解的名称,
它是一个公共接口,这意味着它可以被任何其他类或接口使用。

总结来说,`Documented` 注解是一个标记,用于指示其他注解应该被
包含在javadoc生成的文档中,并且这个注解在运行时是可用的,只能
用于其他注解类型。这是一个常用的注解,因为它允许开发者控制哪些
注解信息会显示在API文档中。
*/

7.4 @Inherited

被它修饰的Annotation具有继承性;如果类A使用了被Inherittd修饰的Annotation,则其子类B自动具有该注解。(有什么用呢qwq...)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Echo-Nie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值