在写 Java 程序碰到一个问题,而正是这个问题引发了我对字符串的思考,Java 示例代码如下:
- public void TestStr(String success)
- {
- if(success=="Y"){
- System.out.println("Equal");
- }
- else
- {
- System.out.println("Not Equal");
- }
- }
上面的这个函数很简单,但会随着调用的方式的不同而显示出不同的结果:
- public void CallMethod()
- {
- TestStr("Y");//Equal
- TestStr("YY".substring(0,1));//Not Equal
- }
对于这样的一个结果,我们可以先思考一个问题:"==" 这个运算符的作用?
但如果理解上面的代码,我们还要理解 Java 中字符串的机制。由于字符串是比较常用的类型,为了保证性能,所以在设计字符串的时候会有一个 "池" 的概念。
所以对于上面的代码,因为在开始已经创建的 "Y" 字符串,所以后面出生现的所有的 "Y" 都是引用我们当前的 "Y",所以我们就可以理解为什么第一个是打印 Equal,另一个是打印 Not Equal.
而对于. Net 来说,字符串的原理大致相同,如果是相同的代码,但运算的结果是与 Java 不一样的:
我们知道在. Net string 也是引用类型,但当 "==" 作用于两个引用类型的时候,比较则是地址,但在. Net 中字符比较时,比较的却是值。这个归功于. Net 对 "==" 的重载,string 源码。如果想比较地址,则使用 object.ReferenceEquals() 函数。
- public static bool operator == (String a, String b)
- {
- return String.Equals(a, b);
- }
对于. Net 运算符重载的这个动作,个人觉得更贴近日常的使用习惯,因为在编码的过程中,字符串中绝大多数的使用场景都是值,而不是引用。而对 Java 而言,保证的运算的原汁原味,少了人为的封装的干扰,使用是注意区分,习惯了反而觉得更为合理。
字符串是一个特殊的引用对象 ,声明就是创建了一个对象,如果使用 new, 则会重复的创建对象 (Java 中可以使用 new 创建,.Net 中则不允许这样操作),浪费内存,如下:
- String str = new String("1234");
- String str1 = "1234";
两种的定义方式相同,但是使用 new 的时候,又额外分配了内存空间。
- public void CallMethod() {
- String str = "abc";
- AddSuffix(str);
- System.out.println(str); //打印出abc
- }
- public void AddSuffix(String x) {
- x = x + "123";
- }
当我们去调用这个函数的时候,发现 str 的值却没有发生改变。 因为在调用 AddSuffix 函数时,str 把自己作拷贝成一个副本传递给形参 x,当对 x 赋值的时候,系统重新创建了一个字符对象,把引用的地址给 x, 此处是重新创建对象,而不是修改原来的字符串对象(字符串不可更改)。两种方式示意如下:
来源: http://www.cnblogs.com/OceanHeaven/p/7401017.html