目录
  1. 1. JDK8源码–String.trim()
    1. 1.1. trim()方法去掉了哪些字符?
    2. 1.2. trim()/substring()怎样返回字符串对象?
JDK8源码--String.trim()

JDK8源码–String.trim()

一直以来,学习 Java 的路上被无数次的告知String类下的trim()方法时,这个函数的作用是去除字符串两边的空格的。但是无意间打开他的源码却发现并没有只是去除空格那么简单,下面来简单分析下,参考链接

trim()方法去掉了哪些字符?

先看下面代码:

1
2
3
4
String str = "abc\u001E\u001E\u001E\u001F\u001F\u001F";
System.out.println(str);
str = str.trim();
System.out.println(str);

这是在 IDEA 上的效果,我们把他输出一下:

image-20200514104410797

会发现,这个看似乱码的字符被trim()干掉了,我们看一下他的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public String trim() {
//这个 value 是 String 里的 final char[]
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */

while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

原文的”white space“中文直译为”留白“或”空白“,但是常见文档一般翻译为”空格“,而空格的英文一般应译为”blank”或”space”,所以我认为这里的翻译不够准确(当然源码注解也没有写得很清楚),而且会引起歧义。

trim()方法实际上trim掉了字符串两端Unicode编码小于等于32(\u0020)的所有字符。

现在提出另一个问题:

trim()/substring()怎样返回字符串对象?

1
2
3
4
5
6
7
8
public static void main(String[] args) {
String str1 = "abc ";
String str2 = "abc";
String str3 = "abc";
str1 = str1.trim();
System.out.println(str1 == str2); // false
System.out.println(str3 == str2); // true
}

str1.trim()返回的字符串为”abc”,而在常量池中已经确定存在这个”abc”这个String对象,那为何str1==str2不成立呢?
我们看trim()方法的最后一行:

1
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;

也就是说,trim()方法实际上的行为并不是”去掉两端的空白字符“,而是”截取中间的非空白字符“
再看substring()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
//注意这一行会 new String
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}

我们看到,当实际发生了”截取“这个动作的时候,因为此处无法直接声明一个String常量,即substring()无法像我们写String str = “abc”这样直接在常量池中创建对象,所以它返回的是一个new出来的对象,这个对象位于Heap内存中。

文章作者: Archiver
文章链接: https://www.kaiming66.com/2020/05/14/JDK8%E6%BA%90%E7%A0%81/JDK8%E6%BA%90%E7%A0%81--String.trim()/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Archiver`s Blog
打赏
  • 微信
  • 支付寶

评论