sharky的点滴积累

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  56 随笔 :: 104 文章 :: 10 评论 :: 0 Trackbacks

      网上关于String类一些有关问题的讨论很多,在这里自我总结一下。希望对刚开始学Java的朋友一对帮助。

【问题一:字符串的引用比较问题】
先看个例子,大家预测下结果:
例1
package base;

public class StringTest
{
    public static void main(String[] args) 
   {
    String A = "test";
    String B = "test";
    String C = new String("test");
    String D = new String("test");
    System.out.println("A==B?" + (A == B));
    System.out.println("C==D?" + (C == D));
    System.out.println("C==A?" + (C == A));
    System.out.println("C equals D?" + (C.equals(D)));

  }
}

运行结果:
A==B? true
C==D?false
C==A?false
C equals D?true

几点认识:

1.引用之间的“=="操作符,表示比较两边引用是否相等,即是否指向同一个对象。
2.对于"String A = "test""这样建立的字符串对象,如果在下次"String B = "test"",如果内容一样,JVM就不会在创建新的对象,而是简单地把新的引用指向已经存在的对象(编译时)。(即便是在不同的包中)
3.String.equals(String)是比较字符串的内容。

理解这几点,通过分析,很快得出上例结果。
这里再给出个例子
例2.

String s1 = "I love Java";
String s2 = "I love ";
String s3 = "Java";
String s4 = s2 + s3;
String s5 = "I love "+"Java";

if (s1 == s4) System.out.println("yes");
else System.out.println("no");

if (s1 == s5) System.out.println("yes");
else System.out.println("no");

运行结果:
no
yes

分析:s2+s3虽然其内容也是"I love Java",但是s4 的值是运行后出来的,不是编译的时候。JVM只是把编译时 "=" 方式创建的 String 对象优化为内容相同时指向相同的对象实体。而当一个字符串由多个字符串常量连接而成时,在编译期就解析为一个字符串常量。s5就是这样,自然打出"yes"。
        有的说String+String中的"+"时JVM自动重载的,用于连接字符串,String s1="java"是对"="的重载,重载为创建一个对象,并把对象地址赋给引用。本质是一样。




----------------------------------
【问题二:Java的参数传递问题】
引出:论坛上一个朋友提出的一道华为的面试题:

例3:
package test;

public class TestString {
public TestString() {
}

public static void main(String[] args) {
String s=new String("Hello");
modify(s);
System.out.println("s = "+s);
}

public static void modify(String s)
{
s+="world";
}
}


运行结果:
s = Hello
为什么是输出Hello,而不是Helloworld?谢谢

------------------------

首先要确认的几点认识:
1.引用不是对象,它没有属性和方法,而是指向某一个对象的变量,跟基本数据类型的变量意义一样。(引用是C中指针的隐藏化)

例4:
             String a ="Hello World";
            String b =a;

分析:a,b是不同的引用变量,但是都是指向同一个对象,即对象"String World"。a,b都是存放了同一个对象的地址,而这个地址指向内存域存放的是"Hello World".

2.Java中的参数传递都是值传递,都是拷贝式的,基本数据类型是这样,不用多说,当传入的参数是一个对象的引用时,也时值传递,只不过传递的"值",非对象本身,而是对象杂在内存中的地址。
       所以在例1中:modify(String s)的"s"得到是String s=new String("Hello")中的"s"的引用值拷贝.

3. String是常量性的,看看JDK文档里面怎么说String的吧,“Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared”。String的内容是无法改变的,如果需要改变,要考虑用StringBuffer。

例5:
         1、 String s = "Hello";
         2、 String s1 = s;
         3、 s1 += "World!";

分析:
      1->2步:s1和s这两个引用,都指向同一个字符串对象"Hello",此时有2个引用,1个对象
     第3步:   由于String的不可更改性,所以“+=”操作后面操作是:返回一个新的字符串"HelloWorld",并把这个新的字符串的地址给引用s1,而引用s仍然引用原来的"Hello"。
此时,有2个引用("s","s1"),两个字符串对象("Hello","HelloWorld")。大家要记住:String的值的改变其实是创建一个新的String对象.
 即:
            s1 += "World!";

           s1 = new String("HelloWold")
语义上是等价。

何为语义?   简单的说就是”你这条语句背后到底让编译器做了些什么?“

这里在提及一个例子
例6.

public class Test
{
  StringBuffer a ;
  public static void main(String[] args)
  {
   Test test = new Test();
   test.a = new StringBuffer("Hello");
   test.test(test.a);
   
   System.out.println("a is "+ test.a);
   
  }
  
  public  void test(StringBuffer strbuf)
  {
   strbuf.append("World");
   System.out.println(strbuf == a);

  }

运行结果:

true
a is HelloWorld

         那这里"strbuf==a",怎么又为true了呢,并且"a is HelloWorld"了,按上面的道理,不是不会修改数据源吗?注意我们这里运用的是StringBuffer,不同于String,它能修改自己的内容。test方法中传入的strbuf引用的值为a引用值的拷贝值,但是strbuf.append("World")这句话,是通过引用的值,修改了该值指向对象的内容,a可以调用append修改,strbuf自然也可以。所以,最后打印出a的值是strbuf修改后的对象的值。好比往test方法中传入的一个可以操作a所指对象的"句柄",可以让方法里的代码操作目的对象。

         如果理解上面几点,理解起来例3为什么是"Hello",我想就比较容易了。
所以通过这个问题,也告诉我们,在学习语言基础的时候,不光要读懂这个语句怎么写,更应该通过现象看本质,了解语句背后编译器做了些什么,尤其是内存分配上的操作。虽然Java淡化了内存有关的概念,但是了解更多机制,会帮我对计算机编译代码的了解更深一个层次。

-------------------------------

相关问题的参考:
http://www.ideagrace.com/html/doc/2005/09/19/00626.html

http://www.matrix.org.cn/thread.shtml?forumId=1&topicId=1142&page=1

http://www.matrix.org.cn/thread.shtml?forumId=1&topicId=27155&page=1

posted on 2005-10-02 12:17 sharky的点滴积累 阅读(311) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: