没想到枚举Enum类还能实现接口!教你玩转Java枚举Enum

枚举是什么?

枚举是一种特殊的数据类型,预先定义一组常量(对象),并且必须为其赋值。

Java 枚举类型的基本想法非常简单:

     这些类通过共有的静态final域为每个枚举常量导出一个实例。枚举类型没有可以访问的构造器,所以它是真的final类。客户端不能创建枚举类型的实例,也不能对它进行扩展,因此不存实例,而只存在声明过程的枚举常量。也就是枚举类型是实例受控的。它们是单例(Singleton)的范型化,本质上是单元素的枚举。

枚举使代码更易拓展和不一定代码减少,对比见下:

我们使用1234用来表示一年中的四个季节

1、常规代码

     public String getSeasonString(Integer key) {         switch (key) {             case 1:                 return "SPRING";             case 2:                 return "SUMMER";             case 3:                 return "AUTUMN";             case 4:                 return "WINTER";             default:                 return null;         }     }

2、使用枚举

 

 // 定义枚举类 @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum SeasonTwoArgs {      /**      * 春天      */     SPRING(1, "春天"),     SUMMER(2, "夏天"),     AUTUMN(3, "秋天"),     WINTER(4, "冬天");      Integer key;     String msg;      SeasonTwoArgs(int key, String season) {         this.key = key;         this.msg = season; //        System.out.println("初始化:" + this.name() + "," + this.msg + "," + season);     }      // 很多情况,我们可能从前端拿到的值是枚举类的 key ,然后就可以通过以下静态方法获取到对应枚举值     public static SeasonTwoArgs valueofKey(Integer key) {         for (SeasonTwoArgs season : SeasonTwoArgs.values()) {             if (season.key == key) {                 return season;             }         }         throw new IllegalArgumentException("No element matches " + key);     }      public String getMsg() {         return msg;     }      public int getKey() {         return key;     }      public void setKey(int key) {         this.key = key;     }      public void setMsg(String msg) {         this.msg = msg;     }          // 获取 季节的方法     public String getSeasonString(Integer key) {         return SeasonTwoArgs.valueofKey(key).msg;     }

有人说了,在使用的时候,我都是调工具类里面的getSeasonString(String key)方法啊!

对比看来,发现代码并没有减少,反而增加了。

但是,如果后期发生了改变,使用枚举更加的方便,也不会影响到之前的业务逻辑。

枚举的要求:

  • 它们限制了列名变量可以采取的值。

  • 它们迫使您考虑列名可以采取的所有可能的值。

  • 它们是一个常数,而不是一个数字,增加了源代码的可读性

自定义多参数枚举

代码见上。

枚举类型保证了编译时的类型安全。包含同名常量的多个枚举类型可以在一个系统中和平共处。因为每个类型都有自己的命名空间。可以新增或者重新排列枚举类型中的常量,而无需重新编译它的客户端代码。

枚举 使用 == 的安全性

1、代码编译时期:

如果俩个枚举类型不同,编译就会报错。

         if (Season.SPRING.equals(TestSeason.AUTUMN)) ; // 编译正常
         if (Season.SPRING == TestSeason.AUTUMN) ;      // 编译失败,类型不匹配

2、运行时期:

Season season = null;System.out.println(season == Season.SPRING);//正常运行System.out.println(Season.SPRING.equals(season));//正常运行System.out.println(season.equals(Season.SPRING));//空指针异常

switch中使用枚举

将枚举作为switch的参数

​​​​​​​

         switch (season) {             case SPRING: {                 System.out.println(1);                 return 1;             }             case SUMMER: {                 System.out.println(2);                 return 2;             }             case AUTUMN: {                 System.out.println(3);                 return 3;             }             case WINTER: {                 System.out.println(4);                 return 4;             }             default:                 System.out.println(0);                 return 0;         }

如何输出JSON

1、自定义toJSONString方法

​​​​​​​

     public String gtoJSONString() {         JSONObject object = new JSONObject();         object.put("name", this.getName());         return object.toJSONString();     }

2、借助jackson工具

​​​​​​​

 1、类上面增加注解: @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum Season {      2、get方法或者基本属性增加注解: @JsonProperty("name") public String getName() { return this.name(); }

重写方法

 /**  * 枚举计算类  */ public enum Operation {     PLUS("+") {         @Override         public double apply(double x, double y) {             return x + y;         }     }, MINUS("-") {         @Override         public double apply(double x, double y) {             return x - y;         }     }, TIMES("*") {         @Override         public double apply(double x, double y) {             return x * y;         }     }, DIVIDE("/") {         @Override         public double apply(double x, double y) {             return x / y;         }     };      private final String symbol;      Operation(String symbol) {         this.symbol = symbol;     }      public abstract double apply(double x, double y);      @Override     public String toString() {         return symbol;     }      public static void main(String[] args) {         double x = 4;         double y = 2;         for (Operation operation : Operation.values()) {             System.out.printf("%f %s %f = %f%n",                     x, operation, y, operation.apply(x, y));         }     } }

通过接口扩展枚举

虽然枚举类型是不可扩展的,但是接口类型确实可扩展的,它是用来表示API中的操作的接口类型。你可以定义另一个枚举类型,它实现这个接口,并用这个新类型的实例代替基本类型。

定义接口

 public interface IOperation {     double apply(double x, double y); }

枚举实现:

 /**  * 枚举计算类  */ public enum Operation implements IOperation{     PLUS("+") {         @Override         public double apply(double x, double y) {             return x + y;         }     }, MINUS("-") {         @Override         public double apply(double x, double y) {             return x - y;         }     }, TIMES("*") {         @Override         public double apply(double x, double y) {             return x * y;         }     }, DIVIDE("/") {         @Override         public double apply(double x, double y) {             return x / y;         }     };      private final String symbol;      Operation(String symbol) {         this.symbol = symbol;     }     @Override     public String toString() {         return symbol;     }     public static void main(String[] args) {         double x = 4;         double y = 2;         for (Operation operation : Operation.values()) {             System.out.printf("%f %s %f = %f%n",                     x, operation, y, operation.apply(x, y));         }      } }

扩展实现乘积运算: 

public enum ExtOperation implements IOperation {      EXP("^") {         @Override         public double apply(double x, double y) {             return Math.pow(x, y);         }     };     private final String symbol;      ExtOperation(String symbol) {         this.symbol = symbol;     }      @Override     public String toString() {         return this.symbol;     }          //入参实现IOperation接口并且是枚举类型。这个可以将该限定去掉,只要实现IOperation接口即可。     private static <T extends Enum<T> & IOperation> void test(Class<T> tClass, double x,                                                               double y) {         for (IOperation operation : tClass.getEnumConstants()) {             System.out.printf("%f %s %f = %f%n",                     x, operation, y, operation.apply(x, y));         }     }      public static void main(String[] args) {         test(ExtOperation.class,2,3);//使用扩展实现枚举对象         test(Operation.class,2,3);//使用默认的实现     }  }

可见:

枚举类型可以添加任意的方法和域,并实现任意的接口。它们提供了所有的Object方法的高级实现,实现了Comparable和Serializable接口,并针对枚举类型的可任意改变性提供了序列化方法。

EnumSet和EnumMap

1、EnumSet

EnumSet 是一种专门为枚举类型所设计的 Set 类型。

与HashSet相比,由于使用了内部位向量表示,因此它是特定 Enum 常量集的非常有效且紧凑的表示形式。

EnumSet 是抽象类,其有两个实现:RegularEnumSet 、JumboEnumSet,选择哪一个取决于实例化时枚举中常量的数量。但是 RegularEnumSet 和JumboEnumSet无法实例化,访问访问不是public​​​​​​​

     public void testEnumSet() {         // 使用场景 可用于 一批数据中,计算数据处于某种状态的有多少条/是否包含等         final EnumSet<Season> enumSet = EnumSet.of(Season.SPRING, Season.WINTER);         System.out.println("enumSet = " + enumSet);         enumSet.add(Season.SUMMER);         System.out.println("enumSet = " + enumSet);          System.out.println("enumSet.contains(Season.SPRING) = " + enumSet.contains(Season.SPRING));     }

2、EnumMap

EnumMap是一个专门化的映射实现,用于将枚举常量用作键。与对应的 HashMap 相比,它是一个高效紧凑的实现,并且在内部表示为一个数组: 

   @Test     public void testEnumMap() {         //EnumMap是一个专门化的映射实现,用于将枚举常量用作键。         final EnumMap<Season, List<Person>> enumMap = new EnumMap<>(Season.class);          // 写一个投票的场景, 模拟10个人 回答自己喜欢的季节         for (int i = 0; i < 10; i++) {             List<Person> personList = null;             Season season = null;             if (i < 3) {                 season = Season.SPRING;             } else if (i < 4) {                 season = Season.SUMMER;             } else if (i < 5) {                 season = Season.AUTUMN;             } else {                 season = Season.WINTER;             }             if (enumMap.containsKey(season)) {                 personList = enumMap.get(season);             } else {                 personList = new ArrayList<>();             }             personList.add(new Person("name" + i, String.valueOf(i % 2), i + 18));             enumMap.put(season, personList);         }         enumMap.forEach((k, v) -> {             System.out.println("喜欢" + k + "有" + v.size() + "个");         });         // 输出:          /**          * 喜欢SPRING有3个          * 喜欢SUMMER有1个          * 喜欢AUTUMN有1个          * 喜欢WINTER有5个          */     }

关于实现单例模式,天生就是单例模式!

 

关注公众号,点击关于我,加入QQ群,私聊群主可以联系到我哦,群文件有Java面试以及框架如何使用pdf等免费资源!!!

发哥讲Java

图片                

如果你觉得文章还不错,就● 扫码关注我们吧~

备注:如需搬迁或者转载,请备注原本链接

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java中的枚举型可以通过以下步骤将其存储到MySQL中: 1. 在MySQL数据库中创建一个包含枚举常量的列,例如: ``` CREATE TABLE example ( id INT NOT NULL AUTO_INCREMENT, enum_col ENUM('VALUE1', 'VALUE2', 'VALUE3'), PRIMARY KEY (id) ); ``` 2. 在Java中定义一个枚举型,并添加一个字段来保存枚举常量的值: ``` public enum ExampleEnum { VALUE1("VALUE1"), VALUE2("VALUE2"), VALUE3("VALUE3"); private final String value; ExampleEnum(String value) { this.value = value; } public String getValue() { return value; } } ``` 3. 在Java中使用JDBC将枚举型转换为字符串型,并将其保存到MySQL中: ``` // 获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/example_db", "username", "password"); // 准备SQL语句 String sql = "INSERT INTO example (enum_col) VALUES (?)"; PreparedStatement stmt = conn.prepareStatement(sql); // 将枚举型转换为字符串型 ExampleEnum exampleEnum = ExampleEnum.VALUE1; String enumValue = exampleEnum.getValue(); // 设置参数并执行SQL语句 stmt.setString(1, enumValue); stmt.executeUpdate(); ``` 4. 在Java中从MySQL中读取枚举型,并将其转换回Java中的枚举型: ``` // 准备SQL语句 String sql = "SELECT enum_col FROM example WHERE id = ?"; PreparedStatement stmt = conn.prepareStatement(sql); // 设置参数并执行SQL语句 stmt.setInt(1, 1); ResultSet rs = stmt.executeQuery(); // 读取结果集并将其转换回Java中的枚举型 if (rs.next()) { String enumValue = rs.getString("enum_col"); ExampleEnum exampleEnum = ExampleEnum.valueOf(enumValue); } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

航迹者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值