Java string.trim()究竟去掉了什么
String.Trim()方法到底為我們做了什么,僅僅是去除字符串兩端的空格嗎?
- trim()方法去掉了哪些字符?
- trim()/substring()怎樣返回字符串對象?
trim()方法去掉了哪些字符?
在Stack Overflow上看到一個問題(點此查看):
I am receiving a string from server trailing one or two lines of spaces like below given string.
String str = "abc*******
********";
Consider * as spaces after my string
i have tried a few methods like
str = str.trim();
str = str.replace(String.valueOf((char) 160), " ").trim();
str = str.replaceAll("\u00A0", "");
but none is working. Why i am not able to remove the space?
為此看了一下trim()方法的源碼,發(fā)現(xiàn)挺有意思的。
先看下面的代碼:
public static void main(String[] args) {
String str = "abc";
System.out.println(str.length());
str = str.trim();
System.out.println(str.length());
}
我不清楚各位在剛學習Java的時候老師(或者書上)是怎么說的,我入門是看畢向東老師的視頻,當時畢向東老師說的是trim()方法會去掉字符串兩端的空格;后來看《Java核心技術(shù)》的時候,書上說的時“返回一個新的字符串。這個字符串將刪除了原始字符串頭部和尾部的空格?!保ǖ?版的中文版,在卷一51頁20行。)所以我一直理所當然地認為trim()方法會trim掉字符串兩端的“空格”,也正是如此,我看到源碼的時候才會覺得很有意思。
不說別的,上面代碼輸出的是9、3,也就是字符串尾部的””被trim()掉了。
更有意思的是,如果你把上面的代碼copy到Notepad++上,它長成這樣:

而在Eclipse上,它長這樣:

沒錯,這個特殊的符號在Eclipse上是看不到、不占任何“空間”的,如果我們不小心在代碼中混入這樣的字符,估計排錯會很痛苦……
再接入正題,現(xiàn)在我們知道了trim()方法不只trim掉空格那么簡單,那么它究竟trim掉了些什么東西?我們不妨來看一下。
/**
* @return A string whose value is this string, with any leading and trailing white
* space removed, or this string if it has no leading or
* trailing white space.
*/
public String trim() {
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“中文直譯為”留白“或”空白“,但是常見文檔一般翻譯為”空格“,而空格的英文一般應(yīng)譯為”blank”或”space”,所以我認為這里的翻譯不夠準確(當然源碼注解也沒有寫得很清楚),而且會引起歧義:trim()方法實際上trim掉了字符串兩端Unicode編碼小于等于32(\u0020)的所有字符。
System.out.println("' '的Unicode編碼為:" + (int)' '); // ' '的Unicode編碼為:32
trim()/substring()怎樣返回字符串對象?
再看另外一個問題:
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”,而在常量池中已經(jīng)確定存在這個”abc”這個String對象,那為何str1==str2不成立呢?
我們看trim()方法的最后一行:
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
也就是說,trim()方法實際上的行為并不是”去掉兩端的空白字符“,而是”截取中間的非空白字符“。
再看substring()方法:
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);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
我們看到,當實際發(fā)生了”截取“這個動作的時候,因為此處無法直接聲明一個String常量,即substring()無法像我們寫String str = “abc”這樣直接在常量池中創(chuàng)建對象,所以它返回的是一個new出來的對象,這個對象位于Heap內(nèi)存中。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
深入理解java動態(tài)代理的兩種實現(xiàn)方式(JDK/Cglib)
本篇文章主要介紹了java動態(tài)代理的兩種實現(xiàn)方式,詳細的介紹了JDK和Cglib的實現(xiàn)方法,具有一定的參考價值,有興趣的可以了解一下2017-04-04
讀取Java文件到byte數(shù)組的三種方法(總結(jié))
下面小編就為大家?guī)硪黄x取Java文件到byte數(shù)組的三種方法(總結(jié))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08
Java在ElasticSearch中使用LocalDatetime類型
最近在開發(fā)一個搜索功能的需求的時候,遇到了LocalDatetime類型不能保存到ElasticSearch中的問題,這篇文章主要介紹了Java在ElasticSearch中使用LocalDatetime類型2023-10-10
詳解Kotlin 高階函數(shù) 與 Lambda 表達式
這篇文章主要介紹了詳解Kotlin 高階函數(shù) 與 Lambda 表達式的相關(guān)資料,需要的朋友可以參考下2017-06-06
Java調(diào)度線程池ScheduledThreadPoolExecutor不執(zhí)行問題分析
最近項目上反饋某個重要的定時任務(wù)突然不執(zhí)行了,很頭疼,開發(fā)環(huán)境和測試環(huán)境都沒有出現(xiàn)過這個問題。定時任務(wù)采用的是ScheduledThreadPoolExecutor,后來一看代碼發(fā)現(xiàn)踩了一個大坑。本文就來和大家聊聊這次的踩坑記錄與解決方法,需要的可以參考一下2023-03-03

