问题的由来

前段时间改游戏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. LeetCode-3LongestSubstringWithoutRepeatingCharacters(C#)

    # 题目 3. Longest Substring Without Repeating Characters Given a string, find the length of the longes ...

  2. Python学习--04条件控制与循环结构

    Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...

  3. javaScript的原型继承与多态性

    1.prototype 我们可以简单的把prototype看做是一个模版,新创建的自定义对象都是这个模版(prototype)的一个拷贝 (实际上不是拷贝而是链接,只不过这种链接是不可见,给人们的感觉 ...

  4. CentOS 7配置LNMP开发环境及配置文件管理

    安装并配置MySQL 5.6 从CentOS从7.x开始默认使用MariaDB.MariaDB完全兼容MySQL,包括API和命令行.但是很多时候我们还是会想要安装MySQL,所以不能直接通过yum命 ...

  5. Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架

    前言: Annotation注解在Android的开发中的使用越来越普遍,例如EventBus.ButterKnife.Dagger2等,之前使用注解的时候需要利用反射机制势必影响到运行效率及性能,直 ...

  6. 第一个移动前端开源项目-dailog

    你还在为手机上没有忙碌光标而发愁吗?你还在抱怨弹出框组件要依赖zepto/jqery吗?你还在纠结是否要自己写一套还是去网上寻找成现成的UI组件吗?YouA为你轻松解决所有烦恼.YouA是我为移动前端 ...

  7. OpenCV人脸识别LBPH算法源码分析

    1 背景及理论基础 人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能,该术语需要和人脸检测进行区分,人脸检测是在一张图片中把人脸定位出来,完成的是搜寻 ...

  8. Redis百亿级Key存储方案(转)

    1 需求背景 该应用场景为DMP缓存存储需求,DMP需要管理非常多的第三方id数据,其中包括各媒体cookie与自身cookie(以下统称supperid)的mapping关系,还包括了supperi ...

  9. 原生js+css3实现图片自动切换,图片轮播

    运用CSS3transition及opacity属性 制作图片轮播动画 自己这两天根据用js来控制触发CSS3中transition属性,从而写出来的以CSS3动画为基础,js控制过程的图片轮播 运用 ...

  10. H3 BPM让天下没有难用的流程之功能介绍

    H3 BPM10.0功能地图如下:  图:H3 BPM 功能地图 一.流程引擎 H3  BPM 流程引擎遵循WFMC 标准的工作流引擎技术,设计可运行的流程和表单,实现工作任务在人与人.人与系统.系统 ...