`
wxyfighting
  • 浏览: 200912 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

java enum的使用以及字符串其字符串之间的转换

 
阅读更多

文章简单,相信在很多网站都能搜索到java enum枚举的使用方式;可能有些东西我当时在刚开始用的时候没找到,所以我写了这篇文章,例如:

大多数地方写的枚举都是给一个枚举然后例子就开始switch,可是我想说,我代码里头来源的数据不太可能就是枚举,通常是字符串或数字,比如一个SQL我解析后首先判定SQL类型,通过截取SQL的token,截取出来可能是SELECT、DELETE、UPDATE、INSERT、ALTER等等,但是都是字符串,此时我想用枚举就不行了,我要将字符串转换成枚举怎么转呢,类似的情况还有从数据库取出数据根据一些类型做判定,从页面传入数据,根据不同的类型做不同的操作,但是都是字符串,不是枚举,悲剧的是我很少看到有人写到这个东西;所以我把它写下来,希望有人能用到。


首先为什么要用枚举?我们在什么时候用枚举比较好,用枚举有啥优势?

我认为哈,当你在一些一个范畴类,并可列举,不变化的类型,用以指导程序向不同的地方路由,用枚举是较好的选择;

听起来有点绕,不过有个例子也许可以明白,例如:

我们可以列举下日常工作日所做的事情:

上班、开会、吃饭、睡觉等

我们可以列举医院五官科需要检查人的部位:

眼睛、鼻子、耳朵、嘴巴等

这些都是可以被列举的,且每种事情我们要用不同的方式去做


当然你可以说:

1、可以用动态方法分派,通过配置文件或annotation;

2、可以使用常量来达到类似的效果;

3、直接通过字符串的equals来表达,用if else来表达


如果用配置加方法分派来做,是灵活,便于修改;但是如果在很多不经常修改的参数上,我们用这中方式往往增加配置的负担,并且当你需要看系统逻辑的时候,需要需要一遍看配置一遍看代码;不过,如果参数是可动态变换的信息,用配置是正确的选择;


而常量的使用,通常在switch case的时候都是数字,字符串在java中是不能做switch case的,使用常量的目的比case 1、case 2 ...这种增加了可读性;但是字符串数据也麻烦,除非再映射一次,那没那个必要,其实枚举也差不多是帮你映射了一次,只是它将代码封装了而已吧了,既然他弄好了,而且语法上支持,干嘛不用呢!其次,常量虽然增加了可读性,不过他没有范畴和管理类型的概念,即一个枚举的定义会定义个范畴,可以很好的将这个范围所需要的东西列举出来,而常量通常是些自己定义的一些池,放在一些公共类中或随机定义,都是比较零散的,并且枚举在switch的时候就明确定义好了就在锁列举的范围内case,既可以控制好系统,增加可读性,并且可以随时查看这个范畴的枚举信息到底有那些,达到类似看配置文件的作用;不过还是回到那句话,如果参数是可变的,那么就不适合做枚举,枚举是一定是可列举的,或者说当前系统考虑范围是可以被枚举的,例如上面的医院五官科,可能还有很多没有列举到,但是当前医院只处理几个部位,不处理其他的,就是这个道理;什么是可变的呢,例如URL参数来分派到对应方法,不可能大家加一段逻辑就去加一个枚举,加一个case,此时用【配置+动态方法分派】更好,当然配置可以用文件或annotation而已。


还有最土的就是,通过字符串equals,用if else来实现,呵呵,这个并没有什么不好,只是这个写比较零散,其次,字符串匹配的equals每次匹配都需要对比每个字符,如果你的代码中大量循环,性能并不是很好,其余的看看上面的描述就更加清楚了;


其次,枚举提供一种类型管理的组件,让面向对象的体系更加完善,使得一些类型的管理既可配置化,并可以管理,在使用枚举的地方都可以沿着枚举的定义找到那些有处理过,那些没处理过,而上述几种很难做到;例如,数据库的操作类型定义了10种,那么再判定的过程中就可以讲枚举像配置文件一样看待,而又非常简单的来管理。


最后,枚举绝对是单例的,对比的性能和数字性能相当,既可以得到可读性,也可以得到性能。


我们先定义个简单枚举(这里只是个例子,就简单定义3个变量了):

public enum SqlTypeEnum {
    INSERT , 
    UPDATE ,
    DELETE ,
    SELECT
}


此时解析SQL后,获取出来一个token,我们要获取这个token的枚举怎么获取呢?

这样获取:

String token = "select";
SqlTypeEnum sqlTypeEnum = SqlTypeEnum.valueOf(token.toUpperCase());


如果没获取到,java会抛出一个异常哦:IllegalArgumentExceptionNo enum const classSqlTypeEnum.XXX


我做大写处理的原因是因为枚举也是大写的(当然如果你的枚举是小写的,那你就小写,不过混写比较麻烦哈),其实valueOf就是调用了枚举的底层映射:



调用的时候会调用这个方法:



所以内部也是一个HashMap,呵呵!


拿到这个信息后,就可以做想要的操作了:

switch(sqlTypeEnum) {
  case INSERT:处理insert逻辑;break;
  case DELETE:处理delete逻辑;break;
 ....
}


OK,有些时候可能我们不想直接用INSERT、UPDATE这样的字符串在交互中使用,因为很多时候命名规范的要求;

例如定义一些用户操作类型:


1、保存用户信息

2、通过ID获取用户基本信息

3、获取用户列表

4、通过ID删除用户信息

等等

我们可能定义枚举会定义为:

public enum UserOptionEnum {
    SAVE_USER,
    GET_USER_BY_ID,
    GET_USER_LIST,
    DELETE_USER_BY_ID
}


但是系统的方法和一些关键字的配置,通常会写成:

saveUser、getUserById、getUserById、deleteUserById

当然各自有各自的规则,不过中间这层映射,你不想做,就一方面妥协,要么枚举名称全部换掉,貌似挺奇怪的,要么方法名称全部换掉,更加奇怪,要么自己做映射,可以,稍微麻烦点,其实也不麻烦?


我们首先写个将枚举下划线风格的数据转换为驼峰的方法,放在一个StringUtils里面:

public static String convertDbStyleToJavaStyle(String dbStyleString , boolean firstUpper) {
        dbStyleString = dbStyleString.toLowerCase();
        String []tokens = dbStyleString.split("_");
        StringBuilder stringBuilder = new StringBuilder(128);
        int length = 0;
        for(String token : tokens) {
            if(StringUtils.isNotBlank(token)) {
                if(length == 0 && !firstUpper) {
                    stringBuilder.append(token);
                }else {
                    char c = token.charAt(0);
                    if(c >= 'a' || c <= 'z') c = (char)(c - 32);
                    stringBuilder.append(c);
                    stringBuilder.append(token.substring(1));
                }
            }
            ++length;
        }
        return stringBuilder.toString();
    }



重载一个方法:

public static String convertDbStyleToJavaLocalStyle(String dbStyleString) {
        return convertDbStyleToJavaStyle(dbStyleString , false);
    }



然后定义枚举:

public enum UserOptionEnum {
    SAVE_USER,
    GET_USER_BY_ID,
    GET_USER_LIST,
    DELETE_USER_BY_ID;

    private final static Map<String , UserOptionEnum> ENUM_MAP = new HashMap<String, UserOptionEnum>(64);


    static {
        for(UserOptionEnum v : values()) {
            ENUM_MAP.put(v.toString() , v); 
        }
    }

    public staticUserOptionEnum fromString(String v) {
        UserOptionEnum userOptionEnum = ENUM_MAP.get(v);
        return userOptionEnum == null ? DEFAULT :userOptionEnum;
    }

    public String toString() {
        String stringValue = super.toString();
        return StringUtil.convertDbStyleToJavaLocalStyle(stringValue);
    }
}

OK,这样传递一个event参数让如果是:saveUser,此时就用:

String event = "saveUser";//假如这里得到参数
UserOptionEnum enum = UserOptionEnum.fromString(event);


其实就是自己做了一个hashMap,我这加了一个fromString,因为枚举有一些限制,有些方法不让你覆盖,比如valueOf方法就是这样。


其实没啥好讲的了,非要说,再说说枚举加一些自定义变量吧,其实枚举除了是单例的外,其余的和普通类也相似,它也可以有构造方法,只是默认情况下不是而已,也可以提供自定义的变量,然后获取set、get方法,但是如果有set的话,线程不是安全的哦,要注意这点;所以一般是构造方法就写好了:

public enum SqlTypeEnum {
   INSERT("insert into"),
   DELETE("delete from")
   ......省略;

   private String name;//定义自定义的变量

   private SqlTypeEnum(String name) {
      this.name = name;
   }

   public String getName() {
       return name;
   }

   public String toString() {
       return name + " 我靠";//重写toString方法
  }
  //一般不推荐
  public void setName(String name) {
        this.name = name;
  }
}


调用下:


SqlTypeEnum sqlTypeEnum = SqlTypeEnum.valueOf("INSERT");
System.out.println(sqlTypeEnum);
System.out.println(sqlTypeEnum.getName());


不推荐也调用下:

sqlTypeEnum.setName("我靠");


在另一个线程:

SqlTypeEnum sqlTypeEnum = SqlTypeEnum.valueOf("INSERT");
System.out.println(sqlTypeEnum);
System.out.println(sqlTypeEnum.getName());


发现结果被改了,呵呵!



分享到:
评论

相关推荐

    编绎原理词法分析和字符串识别-java

    在Java中,字符串是类`String`的对象,因此在词法分析时,需要识别出以双引号开始和结束的字符序列,并将其转换为对应的`String`对象。这个过程中,词法分析器还需要处理转义字符,如"\n"表示换行,"\t"表示制表符。...

    Java中的Enum的使用与分析

    本文将深入探讨Java中`Enum`的基本概念、特性以及如何使用。 #### 二、基本语法与特点 ##### 1. 枚举的基本定义 枚举类型的定义类似于类的定义,但必须使用`enum`关键字。例如: ```java public enum Color { RED...

    java面向程序设计数组、字符串、枚举、泛型的应用[参照].pdf

    可以使用`charAt()`方法获取指定位置的字符,以及`length()`方法获取字符串长度,再配合循环进行计数。 3. **枚举**:枚举是Java中的一种特殊类,用于定义一组预设的常量。实验要求定义一个枚举类型来表示一周的七...

    高阶Java-Java枚举类型 enum 应用详解

    根据字符串转换为对应的枚举实例,如果不存在则抛出异常: ```java Color color = Color.valueOf("RED"); ``` 三、枚举构造器与初始化 1. 枚举构造器: 枚举类型可以有自己的构造器,但只能在枚举声明时使用,并且...

    第8章 枚举,字符串和数组.ppt

    例如,`append(String str)`方法用于向字符串缓冲区追加字符串,`insert(int offset, String str)`方法在指定位置插入字符串,最后`toString()`方法将字符串缓冲区的内容转换为字符串形式。 数组是Java中存储一组...

    Java关于中文乱码问题的多种解决方法

    在进行字符串转换时,如GBK到UTF-8,需要使用`java.nio.charset.Charset`类的`newDecoder()`和`newEncoder()`方法,以及`CharsetDecoder`和`CharsetEncoder`的`decode()`和`encode()`方法。 6. IDE与源代码的编码...

    javaenum学习.pdf

    - 在Web应用中,`valueOf()`方法经常用于根据字符串值获取枚举实例,便于在请求参数和枚举类型间转换。 - 枚举类通常用于表示固定不变的常量集合,如权限级别、状态等,确保了代码的清晰性和安全性。 枚举类型在...

    Java中怎样由枚举常量的ordinal值获得枚举常量对象

    Java1.5提供了关键字enum,能够通过该关键字方便得定义自己须要的枚举类型,比方  enum Season { ...也是说,使用name()方法和valueOf(String)方法能够在枚举类型对象和字符串之间方便得转换。当然,假设valu

    Enum的用法

    同时提供了`valueOf()`方法,用于将字符串转换为相应的枚举值,以及`values()`方法,用于获取所有枚举值的数组。 5. **枚举值的顺序**:`ordinal()`方法返回枚举值在枚举类中的位置,这一顺序由枚举值声明的顺序...

    浅谈Java中是否直接可以使用enum进行传输

    在本文中,我们将探讨 Java 中是否可以直接使用 enum 进行传输,并分析其原因。 首先,我们需要了解枚举类型的序列化问题。在 Java 中,枚举类型可以序列化,因为它继承了 java.lang.Enum 类,该类实现了 ...

    Java常用类讲义大全.docx

    本文主要讲解Java中常用的类,包括字符串类String、StringBuffer、基本类型对应的8个包装类、日期相关类、数字相关类、Random类和Enum类。下面是对每个类的详细解释: 一、String类 String类是不可变类,也就是说...

    Java中的Enum枚举用法.doc

    相比于使用常量接口或字符串来表示固定集合,枚举提供了更加安全且易于管理的方式来处理这些常量。自Java 5起,枚举作为语言的一部分被引入,这极大地增强了其功能性和灵活性。 #### 二、Java枚举的基本概念 1. **...

    Java中enum的用法.pdf

    Java中的枚举(enum)类型是在JDK 1.5版本引入的一种强大的特性,它用于定义一组相关的常量。在C/C++等早期语言中,枚举通常是一...通过利用枚举,开发者可以避免使用硬编码的整数或字符串,提高代码的可读性和安全性。

    json转换jsonschema

    5. **输出JSON Schema**:将生成的JSON Schema对象转换回JSON字符串。 `jsonToSchema-master`可能包含以下内容: - `src`目录:源代码,可能包含实现转换功能的JavaScript文件。 - `dist`目录:编译后的代码,供...

    springboot-fastjson-auto-transform-enum.zip

    它可以直接将Java对象转换为JSON字符串,也可以直接将JSON内容转换为Java对象。这种转换过程非常快速,且内存占用低,是很多Java项目的首选JSON处理工具。 2. **Spring Boot集成Fastjson** 在Spring Boot项目中,...

    动力节点老杜Java基础入门学习教程分享——常用类

    - **编译期**:使用双引号直接赋值的字符串会被放在方法区的字符串常量池中。 - **运行时**:对于运行时动态创建的字符串,如通过字符串连接操作生成的新字符串,它们会被放置在堆中。如果字符串池中已经有了相同...

    在java switch中使用String作为分支条件

    首先,定义一个枚举类型`Animal`,并提供一个静态方法`getAnimal()`用于将字符串转换为对应的枚举值: ```java public enum Animal { DOG, CAT, BEAR; public static Animal getAnimal(String animal) { try { ...

    java常用类详解,java总结文档

    为了处理大小写,我们可以使用`toLowerCase()`和`toUpperCase()`将字符串转换为全小写或全大写,而`trim()`方法会移除字符串两端的空白字符。 除了字符串类,Java还提供了处理时间的类,如`Date`用于表示日期和时间...

    Net与Java常用代码写法对比.docx

    在.NET和Java编程中,有一些常见的代码写法差异,这些差异主要体现在语法、类型转换、枚举处理、字符串操作以及泛型集合的使用上。以下是对这两种语言在这些方面的对比和详细解释: 1. **字符串操作** - .NET中的`...

Global site tag (gtag.js) - Google Analytics