【API知识】类型转换工具ConvertUtils引发的思考
前言
在读取Excel文件数据,有时候不可避免地需要把获取到的字符串转型为基本类型的对象。以前都是自己写转换,难度也不大。后来听说,有可以直接用的轮子——Apache 的commons-beanutils这个包,有提供ConvertUtils。以下我的相关记录。
我要的异常呢?
听说有可以用的轮子,第一反应,肯定是拿来先跑几个测试案例。这东西使用起来也很简单,参数就是源字符串和目的类型。我就先测了一下,一个乱码String转Boolean,看看会不会抛出异常。结果出乎意外的是,它居然没有抛出异常,还返回了false。认真看了一下,才发现它直接把异常打印出来了,还返回了默认值。
代码如下:
public class ConvertTest {
public static void main(String[] args) {
Object result;
result = ConvertUtils.convert("@7##jF*&%#$", Boolean.class);
System.out.println(result);
}
}
输出结果:
真是够呛,你不抛出异常,我留你何用。我就是要你抛出异常,然后我再在上层决定怎么和用户交互,你倒好,直接打印出来了,还给我个默认值,那怎么知道原来的值到底是错误的还是bool false。
于是我想,这种工具都有一个尿性——可配置。我就想肯定有什么方法,比如xxxwithException(),或者throwException()这样的设定。结果翻了一下,还真没有。哇,上头。
内核——ConvertUtilsBean
刚好有时间,于是就看它到底怎么实现的。看了才知道,原来它是把工作委托给ConvertUtilsBean来做的。
public static Object convert(final String value, final Class<?> clazz) {
//这里获取一个ConvertUtilsBean的实例来执行convert方法
return ConvertUtilsBean.getInstance().convert(value, clazz);
}
于是顺藤摸瓜,我就随便翻了翻ConvertUtilsBean。我的眼睛就盯着,看看有没有exception这个关键字,果然让我找到了!!!
public void register(final boolean throwException, final boolean defaultNull, final int defaultArraySize) {
registerPrimitives(throwException);
registerStandard(throwException, defaultNull);
registerOther(throwException);
registerArrays(throwException, defaultArraySize);
}
这里可以配置是否要抛出异常。于是我就用这个bean,测了一下,果然可以。
public class ConvertBeanTest {
public static void main(String[] args) {
ConvertUtilsBean convertUtilsBean = new ConvertUtilsBean();
convertUtilsBean.register(true, false, 0);
Object obj;
obj = convertUtilsBean.convert("@7##jF*&%#$", Boolean.class);
System.out.println(obj);
}
}
输出:
很好,终于抛出异常了。那么,我用这个ConvertUtilsBean就可以了。
ConvertUtilsBean为何能够想转什么就转什么?
实际上,它也不是想转什么就转什么。初始条件下,它内部只注册了基本类型的转换器。
public ConvertUtilsBean() {
converters.setFast(false);
//这个方法是关键,它清除当前所有转换器,并重新初始化
deregister();
converters.setFast(true);
}
public void deregister() { converters.clear(); //false参数表示,是否抛出异常。即默认不抛出异常。
//这里注册了基本类型的转换器
registerPrimitives(false);
registerStandard(false, false);
registerOther(true);
registerArrays(false, 0);
register(BigDecimal.class, new BigDecimalConverter());
register(BigInteger.class, new BigIntegerConverter());
}
注册是什么概念?
“注册”这个词,看上去挺玄乎的,其实一般就是写到一个注册表里面,然后需要的时候从表中检索。在这个实现中,注册表,不过就是一张HashMap。而注册操作,就是把Converter对象放到这个哈希表中。
/**
* The set of {@link Converter}s that can be used to convert Strings
* into objects of a specified Class, keyed by the destination Class.
*/
private final WeakFastHashMap<Class<?>, Converter> converters =
new WeakFastHashMap<Class<?>, Converter>();
我们可以看到,这个表的Key是类型。也就是说,我们在使用convert方法的时候,已经指定了key,自然就找到了对应的Converter。那我们还能想到什么呢,那就是“覆盖”。因为HashMap中,Key是唯一的,所以同种类型的Converter只能存在一个,即新注册的Converter会覆盖同类型的Converter。
对了,忘记提了,这个包有一个Converter接口,如果要自定义的话,也可以自己实现相关的类,注册到这个Bean上,然后统一使用这个Bean。
service provider framework
之所以想到这个,是因为前几天刚刚开始看《Effective Java》这本书中,而里面说的service provider framwork的结构,和这个非常类似。
三个要素:
service接口 => Converter接口
register API => register方法
access API => ConverterUtils工具类
体现的思想就是:客户端和实现类解耦,参照上面的,客户端只要知道ConvertUtils或者ConvertUtilsBean这个类就好了,不需要去记该用哪个Converter。
【API知识】类型转换工具ConvertUtils引发的思考的更多相关文章
- API文档管理工具-数据库表结构思考.
API文档管理工具-数据库表结构思考. PS: 管理工具只是为了方便自己记录API的一些基本信息,方便不同的开发人员 (App Developer, Restful API Developer)之间的 ...
- 由C# dynamic是否装箱引发的思考
前言 前几天在技术群里看到有同学在讨论关于dynamic是否会存在装箱拆箱的问题,我当时第一想法是"会".至于为啥会有很多人有这种疑问,主要是因为觉得dynamic可能是因为有点特 ...
- Spring之LoadTimeWeaver——一个需求引发的思考---转
原文地址:http://www.myexception.cn/software-architecture-design/602651.html Spring之LoadTimeWeaver——一个需求引 ...
- 解决一道leetcode算法题的曲折过程及引发的思考
写在前面 本题实际解题过程是 从 40秒 --> 24秒 -->1.5秒 --> 715ms --> 320ms --> 48ms --> 36ms --> ...
- 【思考】由安装zabbix至排障php一系列引发的思考
[思考]由安装zabbix至排障php一系列引发的思考 linux的知识点林立众多,很有可能你在排查一个故障的时候就得用到另一门技术的知识: 由于linux本身的应用依赖的库和其它环境环环相扣,但又没 ...
- 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考
2018年12月12日18:44:53 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考 案件现场 不久前,在开发改造公司一个端到端监控日志系统的时候,出现了一 ...
- Vue.js 2.x API 知识梳理(一) 全局配置
Vue.js 2.x API 知识梳理(一) 全局配置 Vue.config是一个对象,包含Vue的全局配置.可以在启动应用之前修改指定属性. 这里不是指的@vue/cli的vue.config.js ...
- 由SecureCRT引发的思考和学习
由SecureCRT引发的思考和学习 http://mp.weixin.qq.com/s?__biz=MzAxOTAzMDEwMA==&mid=2652500597&idx=1& ...
- 由<a href = "#" > 引发的思考
原文:由<a href = "#" > 引发的思考 前阵子在一个移动项目中,通过 <a href = "#" > 的方式 绑定clic ...
随机推荐
- Python开发——解释器安装
Python(解释器)安装 Windows 1.Python(解释器)下载链接 2.选择好安装路径,点击安装即可 3.环境变量配置 [右键计算机]-->[属性]-->[高级系统设置]--& ...
- Pandas处理丢失数据
1.创建含NaN的矩阵 >>> dates = pd.date_range(', periods=6) >>> df = pd.DataFrame(np.arang ...
- Java-Selenium,获取下拉框中的每个选项的值,并随机选择某个选项
今天逛51testing,看见有人问这个问题.现在以Select标签为例. 1.首先看页面中的下拉框,如图: 2.F12查看页面源代码,如下 <select class="form-c ...
- bittorrent 学习(一) 种子文件分析与bitmap位图
终于抽出时间来进行 BITTORRENT的学习了 BT想必大家都很熟悉了,是一种文件分发协议.每个下载者在下载的同时也在向其他下载者分享文件. 相对于FTP HTTP协议,BT并不是从某一个或者几个指 ...
- .net 资源释放(托管资源和非托管资源)
1.托管资源 像int.float.DateTime等都是托管资源:net中80%的资源都是托管资源: 托管资源的回收通过GC(垃圾回收器)自动释放分配给该对象的内存,但无法预测进行垃圾回收的时间,我 ...
- MPLAB X IDE V4.15 创建工程,编译,问题处理
初步接触,有错误的地方还请大神们务必提出来,防止误导他人 硬件环境:MCU--PIC18F67K22 仿真下载器--ICD 3 编译环境:MPLAB X IDE V4.15 中文版 工作需要接触到了P ...
- Android使用ksoap2调用C#中的webservice实现图像上传
目录: 一. android使用ksoap2调用webservice 二. 异步调用 三. Android使用ksoap2调用C#中的webservice实现图像上传参考方法 四. 图像传输中Base ...
- 关于SGA中的granule size
1.什么是granule? granule直译为颗粒,ORACLE为SGA 中的组件(eg:log buffer/db buffer/large pool等)分配的最小单元为一个granule. 所以 ...
- 再次理解HTTP请求过程[概念原理篇]
我曾多次阅读http协议,但是理解依然不深,在此,再次阅读,再次理解.加深两点:解析头部信息\r\n,分解头部和主体用\r\n\r\n.之所以一次请求会看到网络里有很多请求,是因为浏览器代替访问了多次 ...
- Spring boot 参数相关注解
最近使用swagger的在线文档调试接口时发现老是报参数问题,最后发现是方法中参数上的注解有问题,今天把填的坑做一下总结. 1. RequestParam 该注解有两个属性: name/value:表 ...