由一篇吐槽对String空字符串判断的文章所引发的碎碎念
一、起因
最近有篇关于String空字符串判断的文章火了,老是看到这篇文章,既然如此我也只好认真看了下:程序员晒出一段代码引来无数网友狂喷!网友:你就活该当码农!
我也觉得这段代码写的不怎么的,首先程序的正确性应该没有问题,我只是觉得如果写出的代码跟道上认可的规范有违的话可能会恶心到后面接手的人而不自知,我现在莫名打喷嚏的时候就在想肯定是在之前公司写的代码又被接手的人吐槽了… :)
看上去就是个判断字符串是否为空字符串的方法,首先这类方法应该提取到StringUtil类似的工具类中,而这个private的权限看上去应该是在调用它的类中找了个宽敞的地就给写上了,这种开发习惯可能会导致项目中存在一些冗余代码。如果对于基础代码的复用没有把握好的话,当项目功能庞大到一定程度的时候用IDEA黑色主题就能看到满满的shi黄色以及后人从头开始阅读项目代码时会不断有这种感觉:啊,这个代码片段我好像刚刚在哪里看到过…个人猜测可能是项目刚刚开发的时候工期比较紧,程序员心想先能跑起来再说反正以后我会重构的,当然大家都懂的,当一个程序员说以后xxx的时候八成回头就忘…然后就这鸟样了。
扯一个话外题,如果细心的话会注意到刚才我说的是StringUtil,关于Util类的命名也有不少的争论,有人认为应该是FooUtils,而有的人认为应该是FooUtil不带s,我个人比较认可的方法是工具类所在的包名带s为com.foo.utils,而其下所放的工具类则不带s为FooUtil,当然只是个人看法,关于这个可以做个试验,在一个依赖开源项目比较多的项目中使用StringUtil为前缀一搜索就能看到不同开源项目也是用哪种方式命名的都有,这个问题还真不太好下定论,反正一个项目中统一用一个风格即可。
然后就是我非常想吐槽的方法名这是导致我写这篇博客的原因,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);
}
上面用到了取反来对表达式结果否定,取反一般脑子会需要急拐弯一下,人脑运算速度稍高不是老司机的话急拐弯容易翻车,所以编程中应该尽量少用取反,为了更好理解可以再稍稍改一下:
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圈有点乱,遇到这种问题还真够喝一壶的。
最后还有一个想法要说,就是看到那篇文章的评论中某高级工程师的回复,很容易让人认为这个行业已经变得是劣币驱逐良币,希望只是刚吃完饭血糖升高判断力降低才导致发言失误。还有就是当名字后面还挂着公司名字时候,说的话是要为公司负责的,你这一时爽了但不小心玩脱了以后让别人怎么看你东家,你看我虽然级别低没title但是写这些没水平的垃圾文章也还是从来不让别人知道我东家是谁免得给东家丢人… :(
二、我对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这种实在没办法忍差太多了…
这个实现大家看了都说不好,很多年了作者也没改,对于这种情况也没什么好办法…
.
由一篇吐槽对String空字符串判断的文章所引发的碎碎念的更多相关文章
- JavaScript空字符串判断
JavaScript空字符串判断 本文完整示例代码GIT仓: 测试用例完整代码:isNullOrEmpty jPublic GIT仓:jPublic 比较常见写法 if (str == 'undefi ...
- 119、Java中String类之通过isEmpty判断是否为空字符串
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- ajax post提交空字符串(string.Empty) MVC接收为null的问题
ajax post提交空字符串(string.Empty) MVC接收为null的问题 这个问题查了好多资料才知道原因: if (bindingContext.ModelMetadata.Conver ...
- 3-java中String值为空字符串与null的判断方法
java中String值为空字符串与null的判断方法 2018年01月21日 14:53:45 阅读数:1189 Java空字符串与null的区别 1.类型 null表示的是一个对象的值,而不是一个 ...
- Java里如何判断一个String是空字符串或空格组成的字符串
要判读String是否为空字符串,比较简单,只要判断该String的length是否为0就可以,或者直接用方法isEmpty()来判断. 但很多时候我们也会把由一些不可见的字符组成的String也 ...
- C# 对象遍历 string类型 null转空字符串和去前后空格
using System; using System.Collections.Generic; namespace OA.Common.Extensions { /// <summary> ...
- java string split 怎么保留尾部空字符串
# 不保留尾部空字符串 public class QQ { public static void main(String[] args) { String str = "a,b,c,d,&q ...
- 如何判断一个String字符串不为空或这不为空字符串
如何判断一个String字符串不为空或这不为空字符串 转载兵哥LOVE坤 最后发布于2018-07-27 00:00:05 阅读数 5144 收藏 展开 1.校验不为空: String str ...
- 如果不空null并且不是空字符串才去修改这个值,但这样写只能针对字符串(String)类型,如果是Integer类型的话就会有问题了。 int i = 0; i!=''。 mybatis中会返回tr
mybatis 参数为Integer型数据并赋值0时,有这样一个问题: mybatis.xml中有if判断条件判断参数不为空时,赋值为0的Integer参数被mybatis判断为空,因此不执行< ...
随机推荐
- PAT甲题题解-1091. Acute Stroke (30)-BFS
题意:给定三维数组,0表示正常,1表示有肿瘤块,肿瘤块的区域>=t才算是肿瘤,求所有肿瘤块的体积和 这道题一开始就想到了dfs或者bfs,但当时看数据量挺大的,以为会导致栈溢出,所以并没有立刻写 ...
- C++ 继承和派生介绍
继承(inheritance)是软件重用的一种方式,程序员通过继承可以吸收已有类的数据和行为来创建新类,并可以添加新的数据和行为来增强类的功能.创建新类时,并不需要创建全新的数据和成员函数,我们可以指 ...
- 从两个设计模式到前端MVC-洪宇
引言 本文将从策略模式和观察者模式两个设计模式讲起,接着过渡到一个经典的复合模式- MVC架构,进而介绍MVC在Web上的适应-Model2架构.之后,我们将视野扩展到前端MVC,看一看前端MVC经典 ...
- 12.23daily_scrum
今天大家的工作重心在调试过程中,以便及时地发现和解决在调试过程中出现的问题和漏洞,悬浮窗测试工作也已经展开,主要集中在边缘设计代码的测试部分,具体工作如下: 具体工作: 小组成员 今日任务 明日任务 ...
- 读书笔记(chapter5)
系统调用 5.1与内核通信 1.系统调用在用户空间进程和硬件设备之间添加一个中间层.作用有三个:它为用户空间提供了一种硬件的抽象接口:系统调用保证了系统的稳定和安全:系统调用是用户空间访问内核的唯一手 ...
- [菜鸟]HTTP 与 HTTPS 的区别
HTTP 与 HTTPS 的区别 分类 编程技术 基本概念 HTTP(HyperText Transfer Protocol:超文本传输协议)是一种用于分布式.协作式和超媒体信息系统的应用层协议. 简 ...
- delphi中登录界面关闭直接现实主界面是怎么回事?
修改工程文件: Application.Initialize; Application.CreateForm(TmainForm, mainForm); Application.ShowMainFor ...
- maven项目编译运行时提示jdk版本过低问题解决方法
明明使用的是1.8jdk,但是运行项目时提示使用的是java版本是1.5,版本过低. 修改pom.xml,添加如下: <build> <plugins> <plugin& ...
- C#动态对象(dynamic)示例(实现方法和属性的动态)
C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点J ...
- IOS AES加密之ECB128模式
1.AES加密模式有好几种,网上大多是CBC.256模式,找了好久才找到解决ECB128模式加密. AES需要导入头文件 #import <CommonCrypto/CommonCryptor. ...