黑马程序员技术交流社区

标题: 字符串创建对象问题 [打印本页]

作者: 马林康    时间: 2012-6-30 19:08
标题: 字符串创建对象问题
  1. public class StringDemo {
  2.         public static void main(String[] args){
  3.                 String a ="ab";
  4.                 String b ="cd";
  5.                 String c ="abcd";
  6.                 String d =a+b;
  7.                 String e ="ab"+"cd";
  8.                 String f =a+"cd";
  9.                 String g ="ab"+b;
  10.                 String h =new String("abcd");
  11.                 System.out.println(c==d);//false
  12.                 System.out.println(c==e);//true
  13.                 System.out.println(c==f);//false
  14.                 System.out.println(c==g);//false
  15.                 System.out.println(c==h);//false
  16.                
  17.                
  18.         }

  19. }
复制代码
上面a+b 和"ab"+"cd" a+"cd"到底有什么区别 搞不清啊

作者: 黑马刘杰    时间: 2012-6-30 19:36
String类型的值是不可更改的,所以每次都需要新创建对象。而String e ="ab"+"cd";这一句并不需要新创建对象,直接指向c就可以了。所以只有c==e为true,其他都是false。
作者: 邓超军    时间: 2012-6-30 19:37
a,b是变量,只包含指向字符串对象的地址,而"ab","cd"是字符串对象,是实际的字符串的值,所以a+b在没有使用其具体值时,只是包含地址的变量,没有具体值的;而"ab"+"cd"得到是一个新的字符串,具有具体值了。那么a+"cd"也就好理解了,是一个含有具体值和地址值的变量。
作者: 黄连兵    时间: 2012-6-30 19:39
03.                String a ="ab";缓存区中创建一个String对象,内容为"ab",

04.                String b ="cd";缓存区中创建一个String对象,内容为"cd",


05.                String c ="abcd";缓存区中创建一个String对象,内容为"abcd",


06.                String d =a+b;因为在编译的时候,是把a和b作为对象来处理的,所以没有简单的去掉"+"号,缓存区中创建一个String对象,内容为"abcd",

07.                String e ="ab"+"cd";编译器编译的时候已经把"+"号去掉了,所以它并没有再新创建对象,而是找到了缓存区里c所指向的那个内容为"abcd"的对象。

作者: Forever。    时间: 2012-6-30 19:55
首先楼主要有一个常量池的概念,这使得代码中的字符串常量只有一个拷贝

而大家都知道==是比较两个对象的内存地址是否相等
System.out.println(c==d);//false       对于String d =a+b; 实际上是在堆里重新创建了一个新的对象,而c是编译器就有的。所以他们的地址一定不同。
System.out.println(c==e);//true      这个其实没有多少好解释的,既然有了常量池这个东西,那么发现有就去拿就可以了。
System.out.println(c==f);//false         String f =a+"cd"; 这个也是同样的道理因为有了a+ 所以会在运行期再次给他分配一个堆的内存。
System.out.println(c==g);//false        道理同上。
System.out.println(c==h);//false         一般出现new这个关键字的时候会在内存中给他单独的给一块儿,所以相对于c从常量池中拿东西,肯定是不一样的。

希望对楼主的理解有帮助
作者: 孙飞    时间: 2012-6-30 20:28
本帖最后由 feigecal 于 2012-6-30 20:42 编辑

因为"ab"和"cd"都是固定的值了,所以"ab"+"cd"也是固定的,它的值在编译时期就会被确定,是存在于栈内存中的字符池中,所以 String e ="ab"+"cd";中e就会在栈中找到"abcd",所以String c ="abcd";中的c和e是相等的。a+b中的a和b在运算出d的值之前,都没有被赋值,他们何时被赋值,以及被赋予什么样的值,JVM是不知道的,相当于都是个变数,因此a和b在被赋值之前,性质类似于一个变量。那么d就不能在编译期被确定,而只能在运行时被创建了,所以+号的作用是返回另外一个新建的String对象,而不是在栈中找string这个值,所以是在堆中存在的。所以String d =a+b;中的d是一个新new的对象,那么d的地址和c的地址自然不是同一个,所以为false。a+"cd"虽然有一个变量,但结果仍是不确定的,和a+b差不多,都是要在堆里新建一个对象返回的。





作者: 自己玩    时间: 2012-6-30 20:43
本帖最后由 自己玩 于 2012-6-30 20:52 编辑

javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,
而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。所以
String d =a+b;是在堆里重新创建了一个新的对象abcd;其他几个和这个道理一样,都有新的对象创建,所以为false
再看String e ="ab"+"cd";在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果abcd,所以“==”的结果是true
String h =new String("abcd"); 这里用到new关键字,所以创建了一个新的abde所以“==”也为false

作者: 王一军    时间: 2012-6-30 22:45





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2