前言

  在读取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引发的思考的更多相关文章

  1. API文档管理工具-数据库表结构思考.

    API文档管理工具-数据库表结构思考. PS: 管理工具只是为了方便自己记录API的一些基本信息,方便不同的开发人员 (App Developer, Restful API Developer)之间的 ...

  2. 由C# dynamic是否装箱引发的思考

    前言 前几天在技术群里看到有同学在讨论关于dynamic是否会存在装箱拆箱的问题,我当时第一想法是"会".至于为啥会有很多人有这种疑问,主要是因为觉得dynamic可能是因为有点特 ...

  3. Spring之LoadTimeWeaver——一个需求引发的思考---转

    原文地址:http://www.myexception.cn/software-architecture-design/602651.html Spring之LoadTimeWeaver——一个需求引 ...

  4. 解决一道leetcode算法题的曲折过程及引发的思考

    写在前面 本题实际解题过程是 从 40秒 --> 24秒 -->1.5秒 --> 715ms --> 320ms --> 48ms --> 36ms --> ...

  5. 【思考】由安装zabbix至排障php一系列引发的思考

    [思考]由安装zabbix至排障php一系列引发的思考 linux的知识点林立众多,很有可能你在排查一个故障的时候就得用到另一门技术的知识: 由于linux本身的应用依赖的库和其它环境环环相扣,但又没 ...

  6. 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考

    2018年12月12日18:44:53 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考 案件现场 不久前,在开发改造公司一个端到端监控日志系统的时候,出现了一 ...

  7. Vue.js 2.x API 知识梳理(一) 全局配置

    Vue.js 2.x API 知识梳理(一) 全局配置 Vue.config是一个对象,包含Vue的全局配置.可以在启动应用之前修改指定属性. 这里不是指的@vue/cli的vue.config.js ...

  8. 由SecureCRT引发的思考和学习

    由SecureCRT引发的思考和学习 http://mp.weixin.qq.com/s?__biz=MzAxOTAzMDEwMA==&mid=2652500597&idx=1& ...

  9. 由<a href = "#" > 引发的思考

    原文:由<a href = "#" > 引发的思考 前阵子在一个移动项目中,通过 <a href = "#" >  的方式 绑定clic ...

随机推荐

  1. [杂谈]杂谈章3 JAVA中如何用自动注入

    PART1 加配置文件 创建自动加载bean的配置文件 <beans xmlns="http://www.springframework.org/schema/beans" ...

  2. TerraGate SFS Manager配置时权限设置问题

    配置SFS Manager时出现以下错误:      "windows account(*\ASPNET) that does not have sufficient permissions ...

  3. vue中的import、export、requre的区别

    在es6之前js一直没有自己的模块语法,为了解决这种尴尬就有了require.js的出现.在es6发布之后js又引入了import的概念使得不清楚两者之间的区别的同学在实际使用过程中造成了自己的误解, ...

  4. Json中对日期的处理

    前言:Json对日期的处理很特别,我们不能简单的转换而得到我们想要的结果,需要进行特殊处理 一.JSon序列化和反序列化对日期的处理 JsonHelper类: using System.IO; usi ...

  5. Python 多进程编程之 进程间的通信(Queue)

    Python 多进程编程之 进程间的通信(Queue) 1,进程间通信Process有时是需要通信的,操作系统提供了很多机制来实现进程之间的通信,而Queue就是其中的一个方法----这是操作系统开辟 ...

  6. 1018 Public Bike Management (30) Dijkstra算法 + DFS

    题目及题解 https://blog.csdn.net/CV_Jason/article/details/81385228 迪杰斯特拉重新认识 两个核心的存储结构: int dis[n]: //记录每 ...

  7. 部署自己配置的nginx到kubernetes,并且能通过ingress访问

    本文的环境介绍 [root@m-30-1 ~]# kubectl version Client Version: version.Info{Major:"1", Minor:&qu ...

  8. RxSwift学习笔记10:startWith/merge/zip/combineLatest/withLatestFrom/switchLatest

    //startWith //该方法会在 Observable 序列开始之前插入一些事件元素.即发出事件消息之前,会先发出这些预先插入的事件消息 Observable.of(1,2,3) .startW ...

  9. HAProxy出现"远程主机强迫关闭了一个现有的连接 " 的错误及解决

    使用haproxy作为sql server 的负载均衡器. 使用了文档中的示例配置项: timeout client 50s        timeout server 50s 采用这个配置项,有时会 ...

  10. docker知识点杂记

    最近重新梳理了一下docker的一些基本知识,简单做了下总结.以后会逐步补充. 1.查看系统内核版本,需要3.10以上 $ uname -r 2.下载docker 说明:centos安装docker比 ...