Java——详细了解枚举类型

1. 引言

因为在项目中,经常会会用到枚举类型。

然后并不清楚枚举类型的使用情景,还有更多的使用习惯。所以在此总结一下。

PS : 新的博客内容,一定要加上目录,要不以后看真不知道自己当时整理了啥。

2. Overview

The enum keyword was introduced in Java 5

Constants defined this way make the code more readable

2.1 枚举的典型应用场景

错误码、状态机等

将常量放到一起,便于管理。

2.2 枚举的本质

其实就是枚举Enum的子类

2.3 怎么看java编译出的class

javac xxx.java 来生成.class

javap xxx.class 们可以查看java编译器生成的字节码,然后用于分解class文件

可以看到java的一些信息

3. abstract class Enum(源码)

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
  
    private final String name;

 
    public final String name() {
        return name;
    }

    private final int ordinal;

 
    public final int ordinal() {
        return ordinal;
    }

 
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }


    public String toString() {
        return name;
    }

  
    public final boolean equals(Object other) {
        return this==other;
    }

  
    public final int hashCode() {
        return super.hashCode();
    }

    protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }


    public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }

  
    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }

 
    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }

    protected final void finalize() { }


    private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
        throw new InvalidObjectException("can't deserialize enum");
    }

    private void readObjectNoData() throws ObjectStreamException {
        throw new InvalidObjectException("can't deserialize enum");
    }
}

4. doc describe

  • Constructor Summary

    Constructors
    ModifierConstructor and Description
    protectedEnum(String name, int ordinal)

    Sole constructor.

  • Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and TypeMethod and Description
    protected Objectclone()

    Throws CloneNotSupportedException.

    intcompareTo(E o)

    Compares this enum with the specified object for order.

    booleanequals(Object other)

    Returns true if the specified object is equal to this enum constant.

    protected voidfinalize()

    enum classes cannot have finalize methods.

    Class<E>getDeclaringClass()

    Returns the Class object corresponding to this enum constant's enum type.

    inthashCode()

    Returns a hash code for this enum constant.

    Stringname()

    Returns the name of this enum constant, exactly as declared in its enum declaration.

    intordinal()

    Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).

    StringtoString()

    Returns the name of this enum constant, as contained in the declaration.

    static <T extends Enum<T>>
    T
    valueOf(Class<T> enumType, String name)

    Returns the enum constant of the specified enum type with the specified name.

 

5. 枚举的使用

5.1 遍历

可以把枚举类型toString();来让他作为String

package a;

public  enum  FruitEnum {
    APPLE,
    PEAR,
    peach;

    //相当于调用Enum(String name, int ordinal):
    //相当于 new Enum<FruitEnum>("APPLE",0); pear也是一样
    public static void main(String[] args) {
        for (FruitEnum e : FruitEnum.values()) {
            System.out.println(e.toString());
        }
    }
}

5.2 静态枚举?

What's the difference between static and non-static enum in Java?

 they are implicitly static by default.

其实他们都是隐式的static的,所以用不用static修饰都行,毕竟是常量

Nested enum types are implicitly static. It is permissible to explicitly declare a nested enum type to be static.

嵌套的枚举类都是静态的。

5.3 关于int ordinal()

int ordinal()  : 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。

这个是我一直比较困惑的点。

其实

public  enum  FruitEnum {
    APPLE,
    PEAR,
    peach;

}

是有这个顺序的默认是0

默认构造函数是

protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

所以上述使用就相当于存了一些String的变量

实际上 enum 就是一个 class,只不过 java 编译器帮我们做了语法的解析和编译

5.4  getDeclaringClass()

package a;

public  enum  FruitEnum {
    APPLE,
    PEAR,
    PEACH;

    public static void main(String[] args) {
        FruitEnum fruitEnum = FruitEnum.APPLE;
        System.out.println(fruitEnum.getDeclaringClass());
    }
}

输出: class a.FruitEnum

目的:返回实例所属的 enum 类型

源码:

  /**
     * Returns the Class object corresponding to this enum constant's
     * enum type.  Two enum constants e1 and  e2 are of the
     * same enum type if and only if
     *   e1.getDeclaringClass() == e2.getDeclaringClass().
     * (The value returned by this method may differ from the one returned
     * by the {@link Object#getClass} method for enum constants with
     * constant-specific class bodies.)
     *
     * @return the Class object corresponding to this enum constant's
     *     enum type
     */
    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }
 所以就是: Returns the Class object corresponding to this enum constant'senum type

5.5 判等操作

package a;

public  enum  FruitEnum {
    APPLE,
    PEAR,
    PEACH;

    public static void main(String[] args) {
        FruitEnum fruitEnum = FruitEnum.APPLE;

        System.out.println("APPLE name(): " + fruitEnum.name());
        System.out.println("APPLE getDeclaringClass(): " + fruitEnum.getDeclaringClass());
        System.out.println("APPLE hashCode(): " + fruitEnum.hashCode());
        System.out.println("equals APPLE: " + fruitEnum.compareTo(fruitEnum.APPLE));
        System.out.println("equals PEACH: " + fruitEnum.equals(fruitEnum.PEACH));
        System.out.println("equals 与0判断: " + fruitEnum.equals(0));
        System.out.format("== 判断: %b\n", fruitEnum == fruitEnum.APPLE);

    }
}

输出结果:

APPLE name(): APPLE
APPLE getDeclaringClass(): class a.FruitEnum
APPLE hashCode(): 1554547125
equals APPLE: 0
equals PEACH: false
equals 与0判断: false
== 判断: true

5.6 其他相关知识

参考:

public enum ErrorCodeEn {
    OK(0) {
        @Override
        public String getDescription() {
            return "成功";
        }
    },
    ERROR_A(100) {
        @Override
        public String getDescription() {
            return "错误A";
        }
    },
    ERROR_B(200) {
        @Override
        public String getDescription() {
            return "错误B";
        }
    };

    private int code;

    // 构造方法:enum的构造方法只能被声明为private权限或不声明权限
    private ErrorCodeEn(int number) { // 构造方法
        this.code = number;
    }

    public int getCode() { // 普通方法
        return code;
    } // 普通方法

    public abstract String getDescription(); // 抽象方法

    public static void main(String args[]) { // 静态方法
        for (ErrorCodeEn s : ErrorCodeEn.values()) {
            System.out.println("code: " + s.getCode() + ", description: " + s.getDescription());
        }
    }
}
// Output:
// code: 0, description: 成功
// code: 100, description: 错误A
// code: 200, description: 错误B

可以这样定义枚举~

5.7 策略枚举

Effective Java 中展示了一种策略枚举。这种枚举通过枚举嵌套枚举的方式,将枚举常量分类处理。

这种做法虽然没有 switch 语句简洁,但是更加安全、灵活。

例:EffectvieJava 中的策略枚举范例

enum PayrollDay {
    MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(
            PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURDAY(
            PayType.WEEKEND), SUNDAY(PayType.WEEKEND);

    private final PayType payType;

    PayrollDay(PayType payType) {
        this.payType = payType;
    }

    double pay(double hoursWorked, double payRate) {
        return payType.pay(hoursWorked, payRate);
    }

    // 策略枚举
    private enum PayType {
        WEEKDAY {
            double overtimePay(double hours, double payRate) {
                return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT)
                        * payRate / 2;
            }
        },
        WEEKEND {
            double overtimePay(double hours, double payRate) {
                return hours * payRate / 2;
            }
        };
        private static final int HOURS_PER_SHIFT = 8;

        abstract double overtimePay(double hrs, double payRate);

        double pay(double hoursWorked, double payRate) {
            double basePay = hoursWorked * payRate;
            return basePay + overtimePay(hoursWorked, payRate);
        }
    }
}
复制代码

测试

System.out.println("时薪100的人在周五工作8小时的收入:" + PayrollDay.FRIDAY.pay(8.0, 100));
System.out.println("时薪100的人在周六工作8小时的收入:" + PayrollDay.SATURDAY.pay(8.0, 100));

 

5.8 总结

enum 是一个普通的 class,它们都可以定义一些属性和方法

不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum

如果枚举中没有定义方法,也可以在最后一个实例后面加逗号、分号或什么都不加。

如果枚举中没有定义方法,枚举值默认为从 0 开始的有序数值

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,前端传递的枚举类型可以通过使用`@RequestBody`注解接收的类中对应的枚举来进行转换。具体实现方式如下所示: 首先,定义一个枚举类,例如`SeasonEnum`,在该枚举类中使用`@JsonFormat(shape = JsonFormat.Shape.OBJECT)`注解来指定序列化的格式。然后在枚举类中定义各个枚举值,并通过私有构造函数设置对应的值和名称。同时,可以使用`@JsonCreator`注解和`getByValue`静态方法来根据值获取对应的枚举值。 接着,在接收数据的类中,比如`TestEnum`和`CooAccountDto`中,可以定义一个枚举类型的属性,例如`private SeasonEnum season;`。然后在对应的getter和setter方法上添加`@JsonFormat(shape = JsonFormat.Shape.OBJECT)`注解。 最后,在后端的接口方法上使用`@PostMapping`注解指定请求路径,并接收一个`TestEnum`对象作为参数。在方法内部,可以通过`testEnum.getSeason()`获取前端传递的枚举类型,并进行后续的操作。 以上就是将Java前端传递的枚举类型转换为后端枚举类型的方式。通过以上步骤,可以方便地在前后端之间进行枚举类型的传递和转换。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [前端传输json数据,后端如何用枚举接受](https://blog.csdn.net/weixin_66521221/article/details/123113399)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [前端传值后端枚举接收](https://blog.csdn.net/Json_Marz/article/details/119248493)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值