如下代码
String s1="abc";
String s2="abc"+"d";
String s3=s1+"d";
String s4="abcd";s2==s4; trues3==s4; false我们知道s2,s4都是指向常量池中内存"abcd",所以地址相同那么s3指向哪里,各位知道吗????

解决方案 »

  1.   

    在书看到,说一个对象的哈希码,代表对象在内存当中的地址。如果两个引用的哈希码一样,说明指向了内存中的同一个对象。
    就此我写了下面的代码,结果是s2,s3,s4这三个引用都指向了同一对象,我也不知道是什么回事,和楼上一样,期待高手解答。个人认为,JVM虚拟机应该做了优化吧,s2,s3,s4表达式右边的结果都是“abcd”,JVM说既然都是指向同一个值,何必要生成三个对象呢?生成一个不就得了吗?不知道这种理解对不?
    public class test
    {
    public static void main (String[] args) {
    String s1="abc"; 
    String s2="abc"+"d"; 
    String s3=s1+"d"; 
    String s4="abcd"; 

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    System.out.println(s3.hashCode());
    System.out.println(s4.hashCode());
        }
    }输出结果:
    96354
    2987074
    2987074
    2987074
      

  2.   

    s3在运行的时候指向了一个堆中的String对象,这个对象的内容是"abcd"
      

  3.   

    两个相同的对象,他们的hashCode肯定相同,不同的两个对象它们的hashCode不一定不相同
      

  4.   

    听说是java的确hashCode 存在问题!
      

  5.   

    后三个的内存地址都相同
    例子:
    int a = 3; 
    int b = 3; 
    编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。 
      

  6.   


    这个是纯粹是因为编译器优化而已。String s2="abc"+"d"; 编译器会直接变成 String s2="abcd"; 因为编译器知道它可以计算出来
      

  7.   

    不是编译器优化,如果你要看String类的源码就可以知道,为什么字符串相同的String变量hashCode也相同。
    public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;            for (int i = 0; i < len; i++) {
                    h = 31*h + val[off++];
                }
                hash = h;
            }
            return h;
        }
    这个完全是根据字符串的内容生成的hash值,所以你要是重写了String的hashCode方法,例如用String对象的引用作为hash值,那么你再打印一下,结果就会不同了。
      

  8.   

    s2和S4相等是编译器优化后,二者都是
    s2="abcd";
    s4="sbcd";
    都是指向常量池,所以相等。
    但是String s3=s1+"d"; 
    在编译器处理后变成了
    s3=new StringBuilder().append(s1).append("d").toString();
    在toString函数当中会创建一个新的String对象,这个对象是堆中的,所以和s4
    不相等。
      

  9.   


        public String toString() {
            // Create a copy, don't share the array
    return new String(value, 0, count);
        }这个是StringBuilder中的toString方法,是创建了一个新的String对象。
      

  10.   


    你可以用JAD等反编译工具看看,String s2="abcd"; 这个是反编译出来的结果。所以s2 == s4 ,但是s3 != s4编译器会尽可能将可以计算出来的结果都预先计算的。