前者是在编译时求值,在编译成class文件之前,编译器已经知道ab的内容是“abc”了,编译器看到a的内容也是一模一样的“abc”,于是就做了个优化,让a和ab引用同一个字符串对象,这样,空间就节省了。后者是在运行时执行完String ab= b+"c";之后,才发现ab的内容是“abc”,如果你说的是真的,那就说明java虚拟机不会像java编译器一样做这种优化。

解决方案 »

  1.   

    为什么这样就行了呢?
    String ab= (b+"c").intern();
      

  2.   

    你不会查JavaDoc啊?intern
    public String intern()
    Returns a canonical representation for the string object. 
    A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification 
    Returns:
    a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.
      

  3.   

    可以说intern方法就是做这件事情的。
      

  4.   

    当JVM装载class文件的时候,JVM会执行常量解析(constant pool resolution)的操作,该操作对字符串的处理过程,包括三个步骤:
    1 如果另一个常量池入口(constant pool entry)被标记为constant-string,并指出同样的unicode字符已经被解析了。那么该项操作的结果就是为之前的常量驰入口创建string实例的引用
    2否则的话 ,如果intern()方法已经被这个常量描叙的一个同样的unicode字符序列的string实例已被调用过了,这个string实例就是该项操作的结果;
    3 一个新的string实例被创建的话,它包含了constant—string入口的描叙的unicode字符序列,这个string实例就是该项操作的结果。
      

  5.   

    (1)我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。  (2)使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。(以上资料来自internet,准确性有待考证,希望对大家有帮助)
      

  6.   

    关键问题是“a==ab”并不是在判断两个string是否相等,而是在判断两个引用是否指向同一个地址。
    String a = new String("abc")
    String b = new String("abc");
    a=b的结果还是false;
    其他的就像楼上几位大侠说得了,String ab= "ab"+"c";,编译器执行到这里的时候会查找常量池,如果能找到"abc",那么就将String ab指向这个"abc",意味着此时"abc"有两个引用,ab和a。
    而String ab=b+"c",编译的时候并不知道b是什么(java的后期绑定策略)。
    有个疑问,此时的ab指向什么?
      

  7.   

    哦,应该是指向了一个新的string。
    java在编译期并不知道ab是什么,只知道是b+"c",b是个String,保证没有出现语法错误。
    在运行期,才知道b="ab",并运行b+"c",构建新的string "abc",并建立一个引用String ab指向这个新的String。
    这样,两次建立的String指向了不同的引用,所以==为false。
      

  8.   

    为什么在编译的时候就能运行"ab"+"c"呢?
      

  9.   

    原题:String和StringBuffer的问题
    String a = "abc";
    String b = "ab";
    String ab= "ab"+"c";
    System.out.println(a==ab);//true String a = "abc";
    String b = "ab";
    String ab= b+"c";
    System.out.println(a==ab);//false为什么两个结果不同?
    原因:
    此题无关乎String or StringBuffered
    此题的原因是在String class中=符号是一个运算符重载,而返回的是一个常量,换句话说
               String a = "abc"  a 指向的是一个常量
    在此题中 String a = "abc"; JDK编译器将会首先生成一个static final常量,然后将地址赋予变量a
    而之后 String ab= "ab"+"c"; 编译器发现依然是一个"abc"的字符串常量,于是又将之前生成的字符串常量地址赋予变量ab
    ab == a比较的是两个String Object所引用的地址,他们属于同一个地址,所以得答案True之后一种做法
    String ab= b+"c"; 
    由于之后产生了一个b实体变量参与运算,导致编译器会再分配一个地址给ab,就相当与new String(),所以当使用ab == a时,引用不同的地址得到的答案是false。这题的关键是如果使用默认的String class 中的 ==运算符号他们将进行地址比较,而非内容比较。
    @.@||~
      

  10.   

    蛮搞的例子,看来java博大精深!
      

  11.   

    也就是说常量之间的运算都是在编译的时候进行?
    int c = 1+2.
    编译的时候jvm已经知道c的值是3了?
      

  12.   

    是这样的。
    所以
    public static final int SECONDS_IN_ONE_DAY = 86400;
    还不如:
    public static final int SECONDS_IN_ONE_DAY = 24 * 60 * 60;
    后者可读性更好,而生成的结果是一样的。
      

  13.   

    对intern还不是很清楚,
    既然ab="ab"+"c"在编译时获得了一个地址,ab=b+"c"在运行时是如何用intern把自己的地址修改为和"ab"+"c"一致的。
    对zyyhero2001(风之传说)贴的步骤 不是很明白
      

  14.   

    To: 楼上小兵
        其实zyyhero2001兄说得有些不正确,在这里其实是因为"ab"+"c" is a final static entity,而b + "c" is only a entity, not final static。
        具体步骤参照第11层楼
    @.@||~