使用valueOf前必须进行校验

每个枚举都是java.lang.Enum的子类,都可以访问Enum类提供的方法,比如hashCode(),name(),valueOf()等.....

其中valueOf()方法会把一个String类型的名称转变为枚举项,也就是枚举项中查找出字面值与该参数相等的枚举项,虽然这个方法很简单,但是JDK却做了一个对于开发人员来说并不简单的处理:

看代码:

复制代码
 1 import java.util.Arrays;
 2 import java.util.List;
 3 
 4 public class Client {
 5     public static void main(String[] args) {
 6         //注意summer是小写
 7         List<String> params = Arrays.asList("Spring", "summer");
 8         for (String name : params) {
 9             //查找表面值与name相同的枚举项
10             Season s = Season.valueOf(name);
11             if (s != null) {
12                 // 有该枚举项时的处理
13                 System.out.println(s);
14             } else {
15                 // 没有该枚举项时的逻辑处理
16                 System.out.println("无相关枚举项");
17             }
18         }
19         
20     }
21 
22 }
23 
24 enum Season {
25     Spring, Summer, Autumn, Winter;
26 }
复制代码

运行输出:

复制代码
Spring
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant cn.summerchill.test.Season.summerat java.lang.Enum.valueOf(Unknown Source)at cn.summerchill.test.Season.valueOf(Client.java:1)at cn.summerchill.test.Client.main(Client.java:12)
复制代码

这段代码看起来很完美了,其中考虑到从String转换成枚举类型可能不成功的情况,比如没有匹配到指定的值,此时valueof的返回值应该为空,所以后面又紧跟着if....else判断输出.

但是运行结果抛出异常.报告是无效参数异常...也就说summer(小写s)午饭转换为Season枚举,无法转换那也不应该抛出IllegalArgumentException异常啊,一旦抛出这个异常,后续的代码就不能执行了,这才是要命的,

这与我们的习惯用法不一致,例如我们从List中查找一个元素,即使不存在也不会报错,顶多indexOf方法返回-1.

看源码:

复制代码
 1     public static <T extends Enum<T>> T valueOf(Class<T> enumType,
 2                                                 String name) {
 3         T result = enumType.enumConstantDirectory().get(name);//通过反射,从常量列表中查找.
 4         if (result != null)
 5             return result;
 6         if (name == null)
 7             throw new NullPointerException("Name is null");
 8         throw new IllegalArgumentException(//最后报无效参数异常
 9             "No enum constant " + enumType.getCanonicalName() + "." + name);
10     }
复制代码

valueOf方法先通过反射从枚举类的常量声明中查找,若找到就直接返回,若找不到就抛出无效参数异常.

valueOf方法本意是保护编码中的枚举安全性,使其不产生空枚举对象,简化枚举操作,但是又引入了一个我们无法避免的IllegalArgumentException异常.

可能有读者会所此处valueOf()方法的源代码不对,以上源代码是要输入两个参数,而我们的Season.valueOf()值传递一个String类型的参数.

真的是这样吗?是的,因为valueOf(String name)方法是不可见的,是JVM内置的方法,我们只有通过阅读公开的valueOf方法来了解其运行原理.

在Season枚举类中引用valueOf方法有三个:

但是在Enum的源码中只有一个valueOf()的方法: 其他两个方法都是JVM的内置方法...

问题清楚了,我们有两种方式可以解决处理此问题:

(1)使用try....catch捕获异常

复制代码
            try {Season s = Season.valueOf(name);// 有该枚举项时的处理
                System.out.println(s);} catch (Exception e) {System.out.println("无相关枚举项");}
复制代码

 

(2)扩展枚举类:

由于Enum类定义的方法基本上都是final类型的,所以不希望被覆写,那我们可以学习List和String,通过增加一个contains方法来判断是否包含指定的枚举项,然后再继续转换,看代码:

复制代码
 1 enum Season {
 2     Spring, Summer, Autumn, Winter;
 3     public boolean contains(String _name){
 4         Season[] season = values();
 5         for(Season s:season){
 6             if(s.name().equals(_name)){
 7                 return true;
 8             }
 9         }
10         return false;
11         
12     }
13 }
复制代码

 

 Season枚举具备了静态方法contains()之后,就可以在valueOf前判断一下是否包含指定的枚举名称了,若包含则可以通过valueOf转换为Season枚举,若不包含则不转换.

总结代码:

复制代码
 1 import java.util.Arrays;
 2 import java.util.List;
 3 
 4 public class Client {
 5     public static void main(String[] args) {
 6         // 注意summer是小写
 7         List<String> params = Arrays.asList("Spring", "summer");
 8         for (String name : params) {
 9             // 查找表面值与name相同的枚举项
10 //            Season s = Season.valueOf(name);
11 //            if (s != null) {
12 //                // 有该枚举项时的处理
13 //                System.out.println(s);
14 //            } else {
15 //                // 没有该枚举项时的逻辑处理
16 //                System.out.println("无相关枚举项");
17 //            }
18             if (Season.contains(name)) {
19                 Season s = Season.valueOf(name);
20                 // 有该枚举项时的处理
21                 System.out.println(s);
22             } else {
23 
24                 System.out.println("无相关枚举项");
25 
26             }
27 
28         }
29 
30     }
31 
32 }
33 
34 enum Season {
35     Spring, Summer, Autumn, Winter;
36 
37     // 是否包含指定名称的枚举项
38     public static boolean contains(String name) {
39         // 所有的枚举值
40         Season[] season = values();
41         
42         // 遍历查找
43         for (Season s : season) {
44             if (s.name().equals(name)) {
45                 return true;
46             }
47         }
48         return false;
49     }
50 }
复制代码

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5632706.html,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540223.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多IDC GSLB的部署

之前已经介绍过GSLB的实现原理&#xff0c;这里再向大家讲述一下GSLB经常遇到的部署方式&#xff0c;多IDC的部署。很多大型的企业或业务容灾要求非常高的客户都会部署有多个异地的数据中心&#xff0c;以保证其业务的“全天候”不间断的正常运行&#xff0c;而要整合多个IDC的…

信息系统开发平台OpenExpressApp:【OpenTest】 之 语法及其使用介绍

在OpenTest 之 运行环境准备中介绍了运行自动化测试需要做的一些准备工作&#xff0c;本篇将继续给大家介绍OpenTest的脚本语法以及使用方法&#xff0c;通过学习后读者应该能够开始动手编写UI自动化测试脚本了。 关键字驱动测试 在学习语法之前&#xff0c;需要了解一下关键字…

Oracle 10g 高级安装图文教程(二)

第八步&#xff1a;为了简便起见&#xff08;工作中肯定不安全&#xff09;&#xff0c;选择“所有的帐户都是用同一个口令”&#xff0c;并输入口令&#xff0c;点击“下一步”&#xff1a;本文转自 victoryan 51CTO博客&#xff0c;原文链接:http://blog.51cto.com/victoryan…

Gram matrix 格拉姆矩阵

2019独角兽企业重金招聘Python工程师标准>>> Gram matrix 度量各个维度自己的特性以及各个维度之间的关系。 来自&#xff1a;https://www.zhihu.com/question/49805962?fromprofile_question_card 由感知机&#xff08;对偶感知机中需要计算样本点两两之间的内积和…

MySQL日常应用操作记录

1.知道一个字段名&#xff0c;怎样查到它在数据库里的哪张表里&#xff1f; USE Information_schema;SELECT TABLE_NAME FROM COLUMNS WHERE COLUMN_NAME字段名称; MySQL中查看库表字段信息都在information_schemal中&#xff0c;获取数据字典等信息都要通过这个视图。 如&…

如果只做前端验证的话,谈jjdd.com的看照片功能。

如果你在上海&#xff0c;并且坐过地铁的话&#xff0c;你肯定知道jjdd.com。 这个网站和百合&#xff0c;世纪佳缘类似&#xff0c;都是交朋友的性质。 在jjdd.com中有个很重要的功能&#xff1a;如果你上传的照片比你想看的人少的话&#xff0c;你是不能看她的照片的。 例如如…

升级PowerShell至4.0版本

为了更好的使用Cmder v1.2&#xff0c;不得不升级PowerShell为4.0。 不知道Cmder的&#xff0c;可以点击这里&#xff1a;https://github.com/cmderdev/cmder 和 逆天神器 cmder。 Powershell是运行在Windows机器上实现系统和应用程序管理自动化的命令行脚本环境。 需要.NET环境…

备忘(持续更新。。。)

1、在springmvc这个框架里面&#xff0c;创建新的业务逻辑层&#xff0c;dao、service层至少需要一个接口&#xff0c;项目才能跑起来 2、获取当前用户桌面路径 File desktopDir FileSystemView.getFileSystemView() .getHomeDirectory();String desktopPath desktopDir.getA…

SQL PASS西雅图之行——签证篇

本人有幸通过IT168&itpub的站庆活动http://www.itpub.net/thread-1716961-1-1.html&#xff0c;并应微软邀请参加了在西雅图举办的The Conference for SQL Server Professionals&#xff08;简称SQL-PASS&#xff09;。 SQL-PASS会议计划于2012年11月6日-9日举行&#xff0…

11.python并发入门(part5 event对象)

一、引入event。 每个线程&#xff0c;都是一个独立运行的个体&#xff0c;并且每个线程的运行状态是无法预测的。 如果一个程序中有很多个线程&#xff0c;程序的其他线程需要判断某个线程的运行状态&#xff0c;来确定自己下一步要执行哪些操作。 threading模块中的event对象…

俞永福卸任阿里大文娱董事长,改任 eWTP 投资组长

两天前&#xff08;11月13日&#xff09;&#xff0c;阿里文娱董事长俞永福离职的消息&#xff0c;在互联网圈炸了锅。但很快&#xff0c;俞本人就在微博做了澄清&#xff0c;并称“永远幸福&#xff0c;我不会离开”。然而就在今天&#xff08;11月15日&#xff09;&#xff0…

Linux查看系统cpu个数、核心书、线程数

Linux查看系统cpu个数、核心书、线程数 现在cpu核心数、线程数越来越高&#xff0c;本文将带你了解如何确定一台服务器有多少个cpu、每个cpu有几个核心、每个核心有几个线程。 查看物理cpu个数 cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l 查看核…

Linux基础篇_01_计算机概论

学习资料&#xff1a;《鸟哥的Linux私房菜&#xff08;基础篇&#xff09;》部分&#xff1a;Linux的规划与安装 时间&#xff1a;20130225 学习笔记&#xff1a;计算机定义&#xff1a;接受使用者输入指令与数据&#xff0c; 经由中央处理器的数学与逻辑单元运算处理后&#x…

[3/21]Windows Server 2008时钟方面的改进展示

在Windows Server 2008中的时钟显示和以往Windows Server 2003及以前的版本显示有很大的差别。如果要显示并进行简单的时间修改可以在时钟上双击&#xff0c;会出现如下图所示的界面。在上图中可以调整但无法进行真正的修改&#xff0c;彻底修改需要点击&#xff02;更改日期和…

2Python全栈之路系列之MysQl基本数据类型

Python全栈之路系列之MySQL基本数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的。 MySQL支持多种类型&#xff0c;大致可以分为三类&#xff1a; 数字类型 日期和时间类型 字符串类型 数字类型 类型大小用途BIT-二进制TINYINT1字节小整数值INT or INTEGER4字…

VDI序曲二 RemotoAPP部署

首先&#xff0c;我们需要准备如下角色&#xff1a;沿用VDI序曲一的2台物理服务器以及角色我们在物理服务器1的hyper-v上&#xff0c;我们利用之前我介绍的“服务器虚拟化之准备母盘VHD”的方法再创建如下虚拟机&#xff1a;WIN-RDAPP&#xff1b;WIN-RDWA&#xff1b;WIN-RDCB…

多任务管理类 MutilTaskManager

计算和计算所需的数据能被较为平均的非配到若干task的时候&#xff0c;下面的任务管理类可以提供在大数据大计算量的情况下非精确的控制task的执行数量来限制计算量和内存占用量.下面是代码&#xff08;非线程安全版本&#xff09;&#xff1a; public class MutilTaskManager{…

Node.js meitulu图片批量下载爬虫1.051

原有1.05版程序没有断点续传模式&#xff0c;现在在最近程序基础上改写一版1.051. // // meitulu图片批量下载爬虫1.051 // 用最近的断点续传框架改写原有1.05版程序 // 2017年11月21日 //// 内置https模块 var httpsrequire("https");// 内置http模块 var httprequi…

mysql 5.6.4以上版本innodb支持全文索引的测试

对于mysql 5.6.4以上版本innodb支持全文索引的测试 在mysql官网&#xff0c;innodb引擎在5.6.4版本提供了对全文索引的支持&#xff0c;笔者对此做了测试&#xff0c;发现对中文全文检索的支持依然不理想&#xff0c;但却确实提供了对英文的全文支持。 12.9.5 Full-Text Restri…

EMC VMAX的磁盘构成,fast policy(重要)

首先是流程&#xff0c; 不同种类的磁盘&#xff08;sata&#xff0c;fc&#xff0c;flah&#xff09;->disk group->raid->DATA volume->thin pool->TDEV and BCVDEV (lun) 然后细看&#xff1a; 1&#xff09; 不同种类的磁盘叫做disk&#xff0c;这是可见的物…