由一篇吐槽对String空字符串判断的文章所引起的碎碎念

 

1、原由

最近有篇关于String空字符串判断的文章火了,总是看到这篇文章,既然如此我也只好认真看了下:程序员晒出一段代码引来无数网友狂喷!网友:你就活该当码农!html

image 

我也以为这段代码写的不怎么的,首先程序的正确性应该没有问题,我只是以为若是写出的代码跟道上承认的规范有违的话可能会恶心到后面接手的人而不自知,我如今莫名打喷嚏的时候就在想确定是在以前公司写的代码又被接手的人吐槽了… :)java

image

看上去就是个判断字符串是否为空字符串的方法,首先这类方法应该提取到StringUtil相似的工具类中,而这个private的权限看上去应该是在调用它的类中找了个宽敞的地就给写上了,这种开发习惯可能会致使项目中存在一些冗余代码。若是对于基础代码的复用没有把握好的话,当项目功能庞大到必定程度的时候用IDEA黑色主题就能看到满满的shi黄色以及后人从头开始阅读项目代码时会不断有这种感受:啊,这个代码片断我好像刚刚在哪里看到过…我的猜想多是项目刚刚开发的时候工期比较紧,程序员心想先能跑起来再说反正之后我会重构的,固然你们都懂的,当一个程序员说之后xxx的时候八成回头就忘…而后就这鸟样了。程序员

扯一个话外题,若是细心的话会注意到刚才我说的是StringUtil,关于Util类的命名也有很多的争论,有人认为应该是FooUtils,而有的人认为应该是FooUtil不带s,我我的比较承认的方法是工具类所在的包名带s为com.foo.utils,而其下所放的工具类则不带s为FooUtil,固然只是我的见解,关于这个能够作个试验,在一个依赖开源项目比较多的项目中使用StringUtil为前缀一搜索就能看到不一样开源项目也是用哪一种方式命名的都有,这个问题还真不太好下定论,反正一个项目中统一用一个风格便可。apache

而后就是我很是想吐槽的方法名这是致使我写这篇博客的缘由,validateString是个什么鬼,若是我前面的猜想成立,这个方法是写在调用它的类中的话还好,由于方法名应该反映的是作了什么而不是怎么作,这个方法只是为了校验一个东西是否合法具体怎么作不关心,可是是校验的是什么东西呢?String是啥?这名字更合适的是将validateString的String改成具体指代的概念,好比validateEmail/validateUserName,而若是是在StringUtil类中的话,validateString就太模糊,由于当针对字符串的操做种类比较多的时候,对其命名就应该粒度更细一些,这里我认为在StringUtil中这样的操做一个更合适的方法签名是public boolean isNotEmpty(String s),后面会针对字符串的几种状态及相关方法进行详述。
接下来就是实现了,我也闹不明白为啥搞那么复杂,直接return应该也能够:编程

private boolean validateString(String str) {
	return str != null && !"".equals(str);
}

上面用到了取反来对表达式结果否认,取反通常脑子会须要急拐弯一下,人脑运算速度稍高不是老司机的话急拐弯容易翻车,因此编程中应该尽可能少用取反,为了更好理解能够再稍稍改一下:ide

private boolean validateString(String str) {
	return str != null && str.length() != 0;
}

若是是抽取到StringUtil中的话就是:工具

public static boolean isNotEmpty(String s) {
	return s != null && s.length() != 0;
}

另外还有一个小细节,小括号和花括号之间没有空格,多是代码没有格式化过,应该格式化一下统一风格的。优化

这里还有楼主认为维护别人的代码会让本身不舒服,由于IT行业的特殊性,大部分状况下项目的生命周期都要比开发人员在这个公司的工龄要长,一段代码通过几我的的手是很正常的。这里又想扯一个话外题,就是一个以前看过的例子,具体记不清了大概就是说有我的开发了一套系统,可是留有很大的隐患估计本身也不知道,后来过了好久了问题终于爆发了,关键是这个时候他都升了好几级了暂称他为P3,他直接下属是P2,P2的某个倒霉的直接下属是P1(此处级别绝无映射只是为了方便叙述),P1找到了问题的根源发现是当初开发系统的人的考虑不周致使很难搞而后汇报给了直属领导P2,P2要维护直属领导P3的面子不敢让其知道这是当年P3留下的隐患(表示不理解,这点担当都没有还当啥领导啊…),就想了个孬点让P1在工做时间以外把这个问题解决了不计入正常工做,这样也没必要向上汇报了,而后工做时间照常给他排其它任务,倒霉的P1以为本身很冤就在论坛发帖子把这事捅了出来让你们评理…反正我是被唬得一愣一愣的,感受IT圈有点乱,遇到这种问题还真够喝一壶的。google

最后还有一个想法要说,就是看到那篇文章的评论中某高级工程师的回复,很容易让人认为这个行业已经变得是劣币驱逐良币,但愿只是刚吃完饭血糖升高判断力下降才致使发言失误。还有就是当名字后面还挂着公司名字时候,说的话是要为公司负责的,你这一时爽了但不当心玩脱了之后让别人怎么看你东家,你看我虽然级别低没title可是写这些没水平的垃圾文章也仍是历来不让别人知道我东家是谁省得给东家丢人… :(  设计

 

2、我对String状态的几种理解

String状态指的是一个String类型的变量的值可能会有的几种状态:

null	指针为null
""	空字符串(empty)
"  "	空白字符串(blank)
" aabb " 字符串
"aaccbb" 只含字母
"12345"  只含数字

发现好多人都分不清空字符串(empty)和空白字符串(blank)的区别,空字符串就是长度为0的字符串,空白字符串虽然长度不为0,可是包含的每一个字符都是空白字符,在trim以后长度为0。

下面是几个字符串相关的很经常使用的方法,也是比较通用的概念(都是在字符串指针不为null的前提下):

isEmpty(): 是否空字符串,即字符串的长度为0,好比""

isNotEmpty():对isEmpty取反

 

isBlank():是否空白字符串,即字符串中只有空白字符,好比"\n \r\t"

isNotBlank():对isBlank取反

 

trim():去除字符串两边的空白字符,好比"  foo  "执行trim以后是"foo",具体请见:Java笔记之java.lang.String#trim

trimToEmpty():返回值要么是trim()的结果,要么是空字符串,必定不为null,好比null—> "", "\n\r" –> ""

trimToNull():某些状况下不容许为空字符串,若是为空的话就认为是null,可使用此方法直接将一个空白字符串变为null,好比"\n\r\t" –> null

 

对于字符串的处理应该尽可能使用Apache commons-lang3或者google guava库。

为何要去使用这种开源库而不是本身造轮子?

一个是知名开源库会有社区专门去维护,使用群体比较大,咱们知道当数据量够大的时候规律就比较明显,同理使用的人比较多了以后的一个好处是有BUG会被发现的比较快,可能一个新版本的BUG次日就被发现并贴出官方声明了,而本身写的实现若是没有人帮review的话可能错误只能等出问题的时候才能被发现了。另一个缘由就是知名开源库由于使用的人比较多,你们有各类好的想法都会提出来去讨论应用到这上面,运用集体智慧不断的去完善、优化它,不论是API的设计仍是实现上都会比本身一我的想出来要好一些。

固然硬要抬杠的话总能找到反例,以前碰到过个很奇葩的API实现,就是Apache commons-io的org.apache.commons.io.FileUtils#byteCountToDisplaySize(java.math.BigInteger),代码贴出来感觉一下:

/**
 * Returns a human-readable version of the file size, where the input represents a specific number of bytes.
 * <p>
 * If the size is over 1GB, the size is returned as the number of whole GB, i.e. the size is rounded down to the
 * nearest GB boundary.
 * </p>
 * <p>
 * Similarly for the 1MB and 1KB boundaries.
 * </p>
 *
 * @param size the number of bytes
 * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes)
 * @see <a href="https://issues.apache.org/jira/browse/IO-226">IO-226 - should the rounding be changed?</a>
 * @since 2.4
 */
// See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
public static String byteCountToDisplaySize(final BigInteger size) {
    String displaySize;

    if (size.divide(ONE_EB_BI).compareTo(BigInteger.ZERO) > 0) {
        displaySize = String.valueOf(size.divide(ONE_EB_BI)) + " EB";
    } else if (size.divide(ONE_PB_BI).compareTo(BigInteger.ZERO) > 0) {
        displaySize = String.valueOf(size.divide(ONE_PB_BI)) + " PB";
    } else if (size.divide(ONE_TB_BI).compareTo(BigInteger.ZERO) > 0) {
        displaySize = String.valueOf(size.divide(ONE_TB_BI)) + " TB";
    } else if (size.divide(ONE_GB_BI).compareTo(BigInteger.ZERO) > 0) {
        displaySize = String.valueOf(size.divide(ONE_GB_BI)) + " GB";
    } else if (size.divide(ONE_MB_BI).compareTo(BigInteger.ZERO) > 0) {
        displaySize = String.valueOf(size.divide(ONE_MB_BI)) + " MB";
    } else if (size.divide(ONE_KB_BI).compareTo(BigInteger.ZERO) > 0) {
        displaySize = String.valueOf(size.divide(ONE_KB_BI)) + " KB";
    } else {
        displaySize = String.valueOf(size) + " bytes";
    }
    return displaySize;
}

BigInteger的整除把1.9M算成1M我忍了,1.9T算成1T这种实在没办法忍差太多了…

这个实现你们看了都说很差,不少年了做者也没改,对于这种状况也没什么好办法…

 

.

相关文章
相关标签/搜索