String.Trim()方法到底为我们做了什么,仅仅是去除字符串两端的空格吗?

一直以为Trim()方法就是把字符串两端的空格字符给删去,其实我错了,而且错的比较离谱。

首先我直接反编译String类,找到Trim()方法:

 public string Trim()
{
return this.TrimHelper(WhitespaceChars, 2);
}

TrimHelper方法有两个参数,第一个参数名WhitespaceChars,首字母尽然是大写的,肯定有文章,真不出我所料:

 internal static readonly char[] WhitespaceChars;

这里只是定义它,没有赋值,而且是静态的,我们看看构造函数去,果然找到:

 static String()
{ Empty = " "; WhitespaceChars = new char[] { '/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', '?', ' ', ' ', ' ', ' ', '?', '?', '?', '?', '?', ' ', '?', '?', '/u2028', '/u2029', ' ', '?' }; }
Trim方法就是把字符串两端的这些字符给删去?我很坚定的猜想到。

继续我们的探索,直接反编译TrimHelper,哇,也许这个才是我想要的,私有的TrimHelper方法:

 private string TrimHelper(char[] trimChars, int trimType)
{
int num = this.Length - 1;
int startIndex = 0;
if (trimType != 1)
{
startIndex = 0;
while (startIndex < this.Length)
{
int index = 0;
char ch = this[startIndex];
index = 0;
while (index < trimChars.Length)
{
if (trimChars[index] == ch)
{
break;
}
index++;
}
if (index == trimChars.Length)
{
break;
}
startIndex++;
}
}
if (trimType != 0)
{
num = this.Length - 1;
while (num >= startIndex)
{
int num4 = 0;
char ch2 = this[num];
num4 = 0;
while (num4 < trimChars.Length)
{
if (trimChars[num4] == ch2)
{
break;
}
num4++;
}
if (num4 == trimChars.Length)
{
break;
}
num--;
}
}
int length = (num - startIndex) + 1;
if (length == this.Length)
{
return this;
}
if (length == 0)
{
return Empty;
}
return this.InternalSubString(startIndex, length, false);
}

经过分析和运行,基本上知道了这个方法是干什么的了。

TrimHelper方法有两个参数:

第一个参数trimChars,是要从字符串两端删除掉的字符的数组;

第二个参数trimType,是标识Trim的类型。就目前发现,trimType的取值有3个。当传入0时,去除字符串头部的空白字符,传入1时去除字符串尾部的空白字符,传入其他数值(比如2) 去除字符串两端的空白字符。

最后再看看真正执行字符串截取的方法:

 private unsafe string InternalSubString(int startIndex, int length, bool fAlwaysCopy)
{
if (((startIndex == 0) && (length == this.Length)) && !fAlwaysCopy)
{
return this;
}
string str = FastAllocateString(length);
fixed (char* chRef = &str.m_firstChar)
{
fixed (char* chRef2 = &this.m_firstChar)
{
wstrcpy(chRef, chRef2 + startIndex, length);
}
}
return str;
}

原来也用指针的?第一次看到,效率应该比较高吧。 
最后总结一下: 
String.Trim()方法会去除字符串两端,不仅仅是空格字符,它总共能去除25种字符: 
('/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '?', '/u2028', '/u2029', ' ', '?')

如果你想保留其中的一个或多个(例如/t制表符,/n换行符,/r回车符等),请慎用Trim方法。

请注意,Trim删除的过程为从外到内,直到碰到一个非空白的字符为止,所以不管前后有多少个连续的空白字符都会被删除掉。

最后附上两个相关的方法(也是String类直接提供的),分别去除字符串头部空白字符的TrimStart方法和去除字符串尾部空白字符的 TrimEnd方法:

TrimStart和TrimEnd方法

如果想去除字符串两端其他任意字符,可以考虑Trim他的重载兄弟:String.Trim(Char[]),传入你想要去除的哪些字符的数组。

源码奉上:

 public string Trim(params char[] trimChars)
{
if ((trimChars == null) || (trimChars.Length == 0))
{
trimChars = WhitespaceChars;
}
return this.TrimHelper(trimChars, 2);
}

空格 != 空白字符,删除空格请使用: Trim(‘ ‘);

java.lang.String中的trim()方法的详细说明(转)的更多相关文章

  1. java.lang.String中的replace方法到底替换了一个还是全部替换了。

    你没有看错我说的就是那个最常用的java.lang.String,String可以说在Java中使用量最广泛的类了. 但是我却发现我弄错了他的一个API(也可以说是两个API),这个API是关于字符串 ...

  2. java.lang.String里面的trim()方法——删除首尾空格

    结果如图 package com.softeasy.test1; public class String_trim { public static void main(String[] args) { ...

  3. java.lang.String 类的所有方法

    java.lang.String 类的所有方法 方法摘要 char charAt(int index) 返回指定索引处的 char 值. int codePointAt(int index) 返回指定 ...

  4. java:常用类(包装类,equals和==的比较,Date,java.lang.String中常用方法,枚举enum)

    *包装类: 将基本类型封装成类,其中包含属性和方法以方便对象操作. *byte---->Byte *short--->Short *long--->Long *float---> ...

  5. java.lang.Math中的基本方法

    java.lang.Math类提供的方法都是static的,“静态引入 ”使得不必每次在调用类方法时都在方法前写上类名:             import static java.lang.Mat ...

  6. mybatis invalid comparison: java.sql.Timestamp and java.lang.String报错解决方法

    这个错的意思是:java.sql.Timestamp和java.lang.String无效的比较 错误的原因是:拿传入的时间类型参数与空字符串进行比较就会报这个异常 解决方法:只保留非null判断就可 ...

  7. java基础---->String中的split方法的原理

    这里面主要介绍一下关于String类中的split方法的使用以及原理. split函数的说明 split函数java docs的说明: When there is a positive-width m ...

  8. Java的String中的subString()方法

    方法如下: public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引 ...

  9. java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.String错误的解决方法

    mmobjectid是在Oracle数据库中对应的是Number类型的,在JavaBean中定义的是Long类型的. List<BigDecimal> mmobjidAllFromMars ...

随机推荐

  1. JavaScript 专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路

    拷贝也是面试经典呐! 数组的浅拷贝 如果是数组,我们可以利用数组的一些方法比如:slice.concat 返回一个新数组的特性来实现拷贝. 比如:   var arr = ['old', 1, tru ...

  2. 项目报错 java lang illegalargumentexception error at 0 can t find referenced pointcut

    出现error at ::0 can't find referenced pointcut...这样的错误原因是:如果你用的JDK版本是1.6的话,而引用的aspectjrt.jar是spring-2 ...

  3. Get Sauce(状压DP)

    描述 In order to celebrate the 8th anniversary of ZOJ, LCLL goes to a sauce factory to "Get Sauce ...

  4. 第001弹:Java 中创建对象的4种方式

    Java 是面向对象的语言,不可避免的,“对象”这个概念是 Java 语言的核心部分,这里来简单讨论一下在 Java 中创建一般对象的方法. 总结下来有以下4种创建对象的方法: 使用 new 关键字调 ...

  5. 免安装版MySql安装与配置

    1:在MySql官网下载免安装版 http://downloads.mysql.com/archives/community/ 下载链接 http://downloads.mysql.com/arch ...

  6. 常用的Java基本代码汇总

    1.字符串和整型的相互转换 String a= String.valueOf(2); int i = Integer.parseInt(a); 2. 向文件末尾添加内容 BufferedWriter ...

  7. 【bzoj1191】[HNOI2006]超级英雄Hero - 二分图匹配

    现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金.主持人问题准备了若干道题目,只有当选手正确回答一道题后,才能进入下一 ...

  8. 关于scarpy的一些说明

    一  scrapy添加代理 1 内置代理:os.environ. 固定格式,不推荐 os.environ['http_proxy'] = "http://root:woshiniba@192 ...

  9. poj 3468 线段树成段更新

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 54012   ...

  10. window下golang使用gRPC入门案例&net core客户端

    gRPC是google开源高性能分布式RPC框架,支持http/2 双向数据流传输及Protobuff,可以在任何环境下运行. 它可以有效地将数据中心内和跨数据中心的服务与可插拔支持进行负载均衡,跟踪 ...