问题的由来

前段时间改游戏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. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  2. [C#] 简单的 Helper 封装 -- RandomHelper

    using System; namespace Wen.Helpers { /// <summary> /// 随机数助手 /// </summary> public seal ...

  3. javascript表单的Ajax 提交插件的使用

    Ajax 提交插件 form.js 表单的下载地址:官方网站:http://malsup.com/jquery/form/ form.js 插件有两个核心方法:ajaxForm()和ajaxSubmi ...

  4. Discuz论坛黑链清理教程

    本人亲测有效,原创文章哦~~~ 论坛黑链非常的麻烦,如果你的论坛有黑链,那么对不起,百度收录了你的黑链,不会自动删除,需要你手动去清理. 什么是黑链 黑链,顾名思义,就是一些赌博网站的外链,这些黑链相 ...

  5. 代码的坏味道(21)——中间人(Middle Man)

    坏味道--中间人(Middle Man) 特征 如果一个类的作用仅仅是指向另一个类的委托,为什么要存在呢? 问题原因 对象的基本特征之一就是封装:对外部世界隐藏其内部细节.封装往往伴随委托.但是人们可 ...

  6. continue break 区别

    在循环中有两种循环方式 continue , break continue 只是跳出本次循环, 不在继续往下走, 还是开始下一次循环 break  将会跳出整个循环, 此循环将会被终止 count = ...

  7. JAVA FreeMarker工具类

    FreeMarkerUtil.java package pers.kangxu.datautils.utils; import java.io.File; import java.io.StringW ...

  8. 基于开源项目SharpMap的热力图(HeatLayer)实现。

    当前公司需要一个用时较少的热力图呈现方案,在避免较底层的GDI开发和比较了多家GIS产品的实际效果之后,团队决定用sharpMap的API来实现,由于之前框架采用的是另外一个开源项目GMap.net, ...

  9. nginx安装

    nginx工作模式-->1个master+n个worker进程 安装nginx的所需pcre库[用于支持rewrite模块] 下载软件方法: 搜索 pcre  download 网址:http: ...

  10. Linux硬件IO的优化简介

    Linux硬件IO的优化简介 首先简单介绍下有哪些硬件设备如下(由于硬件种类厂家等各种因素我就不在此多做介绍有兴趣的可以自行学习): 1.CPU:中央处理器,是计算机运算控制的核心部件之一,相当于人的 ...