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()方法的原始碼,發現挺有意思的。
先看下面的程式碼:
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核心技術》的時候,書上說的時“返回一個新的字串。這個字串將刪除了原始字串頭部和尾部的空格。”(第9版的中文版,在卷一51頁20行。)所以我一直理所當然地認為trim()方法會trim掉字串兩端的“空格”,也正是如此,我看到原始碼的時候才會覺得很有意思。
不說別的,上面程式碼輸出的是9、3,也就是字串尾部的””被trim()掉了。
更有意思的是,如果你把上面的程式碼copy到Notepad++上,它長成這樣:
而在Eclipse上,它長這樣:
沒錯,這個特殊的符號在Eclipse上是看不到、不佔任何“空間”的,如果我們不小心在程式碼中混入這樣的字元,估計排錯會很痛苦……
再接入正題,現在我們知道了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“中文直譯為”留白“或”空白“,但是常見文件一般翻譯為”空格“,而空格的英文一般應譯為”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”,而在常量池中已經確定存在這個”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); }
我們看到,當實際發生了”擷取“這個動作的時候,因為此處無法直接宣告一個String常量,即substring()無法像我們寫String str = “abc”這樣直接在常量池中建立物件,所以它返回的是一個new出來的物件,這個物件位於Heap記憶體中。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。