问题的由来

前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了!

事情是这样的,做过游戏的都知道,buff,需要分类型,且包含是否需要切换场景删除,下线删除,死亡删除等信息,好吧我就把这个做到一起了用一个字段标识!

问题就出来了;

/**
 *
 * <br>
 * author 失足程序员<br>
 * mail 492794628@qq.com<br>
 * phone 13882122019<br>
 */
public class EnumTest {

    private static final Logger log = Logger.getLogger(EnumTest.class);

    public enum BuffType {

        Null(0, "空buff"),
        DieDel(62, "死亡删除"),
        ChangeMapDel(63, "切换场景删除");

        int index;
        long value;
        String msgString;

        BuffType(int index, String msg) {
            this.index = index;
            this.value = 1L << index;
            msgString = msg;
        }

        public int getIndex() {
            return index;
        }

        public String getMsgString() {
            return msgString;
        }

        public static BuffType getBuffType(int index) {
            BuffType[] values = BuffType.values();
            for (BuffType buffType : values) {
                if (buffType.getIndex() == index) {
                    return buffType;
                }
            }
            return null;
        }

        /**
         * 是否包含一个状态
         *
         * @param tvalue
         * @return
         */
        public boolean hasFlag(BuffType tvalue) {
            return (value & tvalue.value) != 0;
        }

        /**
         * 增加一个状态
         *
         * @param buffType
         */
        public void addStatus(BuffType buffType) {
            value = value | buffType.value;
        }

        /**
         * 移除一个状态
         *
         * @param buffType
         */
        public void removeStatus(BuffType buffType) {
            value = value & (~buffType.value);
        }
    }

    public static void main(String[] args) {
        BuffType buffType = BuffType.Null;

        buffType.addStatus(BuffType.DieDel);

    }
}

晃眼一看好像没什么问题对吧??当然你已经有过这样一次上当经历的宁说!

解密

当时情况是这样的,我修改完buff功能模块以后我就让策划测试代码功能,我继续改其他功能模块,然后策划告诉我不对,我准备调试的时候可是代码已经不是源代码了,需要重新启动程序才能调试,好吧我重启完成,测试告诉我对了,好吧我又继续该功能模块,过了半小时策划再次告诉我不对了,我又一次的需要重启才能调试,好吧就这样陷入死循环,一直到晚上吃饭我。、我直接说改了一下午代码走出去活动活动吃饭回来继续看,回来后我就不再修改代码,就等测试这个功能;这下发现了情况,

使用流程

    public static void main(String[] args) {
        BuffType buffType = BuffType.Null;

        buffType.addStatus(BuffType.DieDel);
        if (buffType.hasFlag(BuffType.DieDel)) {
            System.out.println("下线需要删除buff");
        }

        buffType = BuffType.Null;

        if (buffType.hasFlag(BuffType.DieDel)) {
            System.out.println("下线需要删除buff");
        }
    }

接下来看看输出结果:

问题来了为什么我明明是新来的一个赋值对象为啥还是包含状态???

我想了一下,突然回过神来,枚举是静态常量啊,我的任何修改都会导致所有引用全部修改,

好吧,既然找到问题了就来修改吧。

再次阐述一下,我这里需要枚举的原因,一个是为了策划配置方便,他们只要1,2,3这种形式

而我需要位移运算,保存状态值,并且还需要枚举类型的文字描述,提供给运维,运营和策划看的。

修改后如何使用

因为我个人喜欢比较喜欢枚举,加上能定义枚举的方便些;

接下来就修改,修改,

 /**
  *
  * <br>
  * author 失足程序员<br>
  * mail 492794628@qq.com<br>
  * phone 13882122019<br>
  */
 public class EnumTest {

     private static final Logger log = Logger.getLogger(EnumTest.class);

     private long tVlaue = 0;

     public enum BuffType {

         DieDel(62, "死亡删除"),
         ChangeMapDel(63, "切换场景删除");

         int index;
         long value;
         String msgString;

         BuffType(int index, String msg) {
             this.index = index;
             this.value = 1L << index;
             msgString = msg;
         }

         public int getIndex() {
             return index;
         }

         public String getMsgString() {
             return msgString;
         }
     }

     /**
      * 根据策划配置还原枚举
      *
      * @param index
      * @return
      */
     public static BuffType getBuffType(int index) {
         BuffType[] values = BuffType.values();
         for (BuffType buffType : values) {
             if (buffType.getIndex() == index) {
                 return buffType;
             }
         }
         return null;
     }

     /**
      * 是否包含一个状态
      *
      * @param tvalue
      * @return
      */
     public boolean hasFlag(BuffType tvalue) {
         return (tVlaue & tvalue.value) != 0;
     }

     /**
      * 增加一个状态
      *
      * @param buffType
      */
     public void addStatus(BuffType buffType) {
         tVlaue = tVlaue | buffType.value;
     }

     /**
      * 移除一个状态
      *
      * @param buffType
      */
     public void removeStatus(BuffType buffType) {
         tVlaue = tVlaue & (~buffType.value);
     }

     public static void main(String[] args) {
         EnumTest buffType = new EnumTest();

         buffType.addStatus(BuffType.DieDel);
         if (buffType.hasFlag(BuffType.DieDel)) {
             System.out.println("包含:" + BuffType.DieDel.getMsgString());
         } else {
             System.out.println("不包含:" + BuffType.DieDel.getMsgString());
         }

         buffType = new EnumTest();

         if (buffType.hasFlag(BuffType.DieDel)) {
             System.out.println("包含:" + BuffType.DieDel.getMsgString());
         } else {
             System.out.println("不包含:" + BuffType.DieDel.getMsgString());
         }
     }
 }

结果:

我知道这篇文字对大神没什么用,希望对新手有所帮助,同时也记录一次犯二的我!

谈谈枚举的新用法——java的更多相关文章

  1. K:java中枚举的常见用法

    用法一:常量   在JDK1.5 之前,我们定义常量都是: public static fianl.....现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. ...

  2. Java枚举类型的用法

    JDK1.5引入了新的类型——枚举.在 Java 中它虽然算个“小”功能,却给我的开发带来了“大”方便. 1.用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fia ...

  3. Java中枚举的常见用法

    在JDK1.5以后引入了一种新的类型,就是枚举(enum).enum是用来声明枚举类型数据,它可以像数组一样存储许多的元素,但是不同于数组的是,它除了数字不能存储以外, 其他类型的如字母.特殊符号.汉 ...

  4. Java SE 枚举的基本用法

    出于对自己基础的稳打,期末考试后依旧对SE部分进行复习 枚举的基本用法 public enum Season { SPRING,SUMMER,AUTUMN,WINTER } public class ...

  5. C++11之for循环的新用法《转》

    相关资料:https://legacy.gitbook.com/book/changkun/cpp1x-tutorial/details C++11之for循环的新用法 C++使用如下方法遍历一个容器 ...

  6. OpenJDK源码研究笔记(十):枚举的高级用法,枚举实现接口,竟是别有洞天

    在研究OpenJDK,Java编译器javac源码的过程中,发现以下代码. 顿时发现枚举类竟然也有如此"高端大气上档次"的用法. 沙场点兵(用法源码) com.sun.tools. ...

  7. 详解Vue的slot新用法

    摘要: 理解Vue插槽. 作者:前端小智 原文:vue 2.6 中 slot 的新用法 Fundebug经授权转载,版权归原作者所有. 为了保证的可读性,本文采用意译而非直译. 最近发布不久的Vue ...

  8. JOptionPane用法--java

    JOptionPane用法--java JOptionPane的简单应用: 1.首先引入包: import javax.swing.JOptionPane; 2.添加如下代码: Object[] op ...

  9. C++虚函数的新用法

    1.今天在segmentfault上看到了一个C++虚函数的新用法,先上代码 #include <iostream> using namespace std; class B { publ ...

随机推荐

  1. netcore - MVC的ActionFilter的使用

    经过一周的时间没有分享文章了,主要是在使用.netcore做一个小的项目,项目面向大众用户的增删改查都做的差不多了,打算本周在云服务器上部署试试,很期待,也希望上线后大家多多支持:以上纯属个人废话,来 ...

  2. C++ 11 多线程--线程管理

    说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...

  3. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  4. AlloyTouch实战--60行代码搞定QQ看点资料卡

    原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/kandian 先验货 访问DEMO你也可以点击这里 源代码可以点击这里 如你体验所见,流程的滚动的 ...

  5. 电信计费业务:预后融合OCS到底应该实扣还是虚扣?

    引入OCS的初衷之一是为了让计费系统能够参与到用户的通讯控制中来,也就是所谓的实时信控.用户在没有余额时,通讯就会被停止,不会造成"天价欠费 ",一方面保障用户的利益,一方面也保障 ...

  6. 快速构建App界面的框架(●'◡'●) -----SalutJs

    前言 卤煮在公司之初接触到的是一个微信APP应用.前端技术采用的是Backbone+zepto等小型JS类库.在项目开发之初,这类中小型的项目采用这两种库可以满足基本的需求.然而,随着迭代的更新和业务 ...

  7. 完成C++不能做到的事 - Visitor模式

    拿着刚磨好的热咖啡,我坐在了显示器前.“美好的一天又开始了”,我想. 昨晚做完了一个非常困难的任务并送给美国同事Review,因此今天只需要根据他们提出的意见适当修改代码并提交,一周的任务就完成了.剩 ...

  8. WPF - 属性系统 (4 of 4)

    依赖项属性的重写 在基于C#的编程中,对属性的重写常常是一种行之有效的解决方案:在基类所提供的属性访问符实现不能满足当前要求的时候,我们就需要重新定义属性的访问符. 但对于依赖项属性而言,属性执行逻辑 ...

  9. Java下好用的开源库推荐

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文想介绍下自己在Java下做开发使用到的一些开源的优秀编程库,会不定 ...

  10. 2000条你应知的WPF小姿势 基础篇<22-27 WPF生命周期, 基础类等>

    端午长假在家陪着女朋友, 幸福感满满,生活对于一只饱经忧患的程序猿来说也是非常重要的,也就暂时没有更新博客.休假结束,回归奋斗的日子了,开始继续更新WPF系列. 在正文开始之前需要介绍一个人:Sean ...