开发中常用的String操作

开发中经常用到的操作有:

  1. 格式化/日志格式化
  2. 字符串判断
  3. 字符串处理,常见的如处理字符串的第一个/最后一个字符

String.format

String.format()是一个格式化的方法,使用%为前缀来表示要格式化的内容占位,一般的使用方法为:

1
String.format("test result is %s", "success");

但是当要格式化的占位符与参数个数不同时会发生什么呢?

占位符个数与参数个数相同

如上代码,可以正常进行输出: test result is success

占位符个数少于参数个数

1
String.format("test result is %s", "success", "other");

可以正常打印,输出结果为: test result is success

占位符个数多于参数个数

1
String.format("test result is %s %s %s", "success", "other");

抛出了异常java.util.MissingFormatArgumentException: Format specifier ‘%s’

问题总结

为什么占位符数少于参数个数可以正常执行,而多于参数个数却报了异常?看JAVADOC发现,如果占位符个数少于参数个数,则多余的参数被忽略,如果多于参数个数,则在进行解析时会判断待处理占位符位置与参数个数,主要代码逻辑如下:

1
2
if (args != null && lasto > args.length - 1)
    throw new MissingFormatArgumentException(fs.toString());

所以在使用String.format方法 切记 要参数个数多于待解析占位符的个数,这种问题常因为Copy操作后,处理了部分参数而忘记对应处理占位符

  • 替换方案

    1. 目前看到很多的老代码打印日志时大都使用String.format(),可以改成slf4j的{}
    2. 还可以使用Apache common utils中的StringUtils.joinWith()或者Google guava的Joiner连接器

Apache commons utils-StringUtils

在StringUtils中有一个isNumeric方法,用来判断字符串是不是数字,那下面的代码会返回什么呢?

1
StringUtils.isNumeric("");

3.0之前StringUtils

StringUtils.isNumeric("") 返回true,有点慌,空串怎么被认为是数字呢?看下代码实现就明白了,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public static boolean isNumeric(String str) {
    if (str == null) {
        return false;
    }
    int sz = str.length();
    for (int i = 0; i < sz; i++) {
        if (Character.isDigit(str.charAt(i)) == false) {
            return false;
        }
    }
    return true;
}

代码中只判断了null,对空串直接就返回ture了

3.0之后StringUtils

StringUtils.isNumeric("") 返回flase了,这才符合正常的使用逻辑,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public static boolean isNumeric(final CharSequence cs) {
    if (isEmpty(cs)) {
        return false;
    }
    final int sz = cs.length();
    for (int i = 0; i < sz; i++) {
        if (!Character.isDigit(cs.charAt(i))) {
            return false;
        }
    }
    return true;
}

由代码可以看出当参数为空串时直接调用isEmpty方法返回false。在工具类使用时还是要使用最新的版本,多关注版本的优化项,多看源码,否则你以为的真的不一定是你以为的。

扩展一下

还有其它的办法可以判断一个字符串是数字了吗?

  • NumberUtils.isParsable(String)

    NumberUtils中提供了isParsable方法,用于判断字符串是否可以进行数字转换

  • NumberUtils.isCreatable(String)

    NumberUtils中提供了isCreatable方法,用于判断字符串是否是一个有效的数字,比isParsable方法判断的范围更大

StringUtils中有用的方法

在开发中,常会取字符串首或尾字符进行判断,比如对尾号进行灰度,那么可以用到以下方法

取字符串前N个字符

StringUtils.left(final String str, final int len)

1
2
3
StringUtils.left("abc", 0)   = ""
StringUtils.left("abc", 2)   = "ab"
StringUtils.left("abc", 4)   = "abc"

取字符串后N个字符

StringUtils.right(final String str, final int len)

1
2
3
StringUtils.right("abc", 0)   = ""
StringUtils.right("abc", 2)   = "bc"
StringUtils.right("abc", 4)   = "abc"

对字符串尾部的操作符进行删除

想删除字符串的尾字符(回车符),可以使用StringUtils.chop(final String str)方法

1
2
3
4
StringUtils.chop("a")           = ""
StringUtils.chop("\r")          = ""
StringUtils.chop("\n")          = ""
StringUtils.chop("\r\n")        = ""