String s1 = "1234";
String s2 = "1234";
String s3 = new String("5678");
String s4 = new String("5678");
上面总共创建了几个对象?s1和s2是不是同一个对象?s3和s4是不是同一个对象?我觉得new后面的”5678“应该是一个对象吧,它存储在堆中。但是这里有两个new ”5678“,那么在第二次new String(”5678“)时会不会因为在堆中已经有存储了一个”5678“对象,所以就不在堆中重新生成了一个”5678“呢?
一共是三个对象,s1和s2是同一个对象,s3和s4是两个不同的对象。所以一共是三个对象,我来简单说明一下吧。
首先你要理解String的一个特性,就是不可变性,也就是说一个String对象创建以后,在第一次为它赋值完成以后,这个String对象的值就不会再发生改变。比如上面的s1="1234",那么对于"1234"这个字符串对象来说,它的内容永远都是"1234"了,这是如果我又写s1=s1+"56",那么结果是s1的值变成了"123456",你可能就会觉得奇怪,不是说字符串不可变,怎么s1变成"123456"了。
这里s1只是变量,它的引用是可以随时变化的,开始它引用的是"1234"这个字符串,后面它引用的是"123456"这个字符串,"1234"和"123456"已经是两个对象了,这就是String的不可变性的实质。
那么在看看s1,s2. s1="1234",这个时候,"1234"这个对象还不存在,所以这里其实就等于s1= new String{"1234"},新建了一个字符串,内容是"1234",然后s2="1234",没用使用new,那么java虚拟机就回去String池去找,有没有内容和"1234"相同的字符串,有的话,s2引用就直接指向它,并且原来的s1的引用依然保留。所以你如果判断s1==s2,那么肯定返回true.
s3,s4就是另一种情况了,虽然他们的值都是"5678",但是全部使用了new关键字,也就等于java虚拟机会强行在内存中生成两个字符串,尽管内容相同,也不会去主动寻找了。s3==s4,肯定是false。
这也就是为什么我们比较两个字符串内容相等时要用equals方法,而不用==了,前者专门比较字符串的值是否相同,后者比较引用是否相同。
希望我的回答能帮助你,很详细了
首先你要理解String的一个特性,就是不可变性,也就是说一个String对象创建以后,在第一次为它赋值完成以后,这个String对象的值就不会再发生改变。比如上面的s1="1234",那么对于"1234"这个字符串对象来说,它的内容永远都是"1234"了,这是如果我又写s1=s1+"56",那么结果是s1的值变成了"123456",你可能就会觉得奇怪,不是说字符串不可变,怎么s1变成"123456"了。
这里s1只是变量,它的引用是可以随时变化的,开始它引用的是"1234"这个字符串,后面它引用的是"123456"这个字符串,"1234"和"123456"已经是两个对象了,这就是String的不可变性的实质。
那么在看看s1,s2. s1="1234",这个时候,"1234"这个对象还不存在,所以这里其实就等于s1= new String{"1234"},新建了一个字符串,内容是"1234",然后s2="1234",没用使用new,那么java虚拟机就回去String池去找,有没有内容和"1234"相同的字符串,有的话,s2引用就直接指向它,并且原来的s1的引用依然保留。所以你如果判断s1==s2,那么肯定返回true.
s3,s4就是另一种情况了,虽然他们的值都是"5678",但是全部使用了new关键字,也就等于java虚拟机会强行在内存中生成两个字符串,尽管内容相同,也不会去主动寻找了。s3==s4,肯定是false。
这也就是为什么我们比较两个字符串内容相等时要用equals方法,而不用==了,前者专门比较字符串的值是否相同,后者比较引用是否相同。
希望我的回答能帮助你,很详细了
温馨提示:答案为网友推荐,仅供参考
第1个回答 2013-11-08
其实楼上的意思都对,但答案并不对.其实正确答案是4个,并不是3个.
首先第一步
String s1 = "1234";时在字符串池中创建了一个1234的对象,指向s1;//这里创建了一个对象
第二步
String s2 ="1234";是先到字符串池中去找,池中有一个1234的对象,直接指向s2;//这里用的是已经有的对象所以并没有重新创建对象,目前还是创建一个对象
第三部
String s3 = new String ("5678");这里创建了两个对象,千万别想错了,是两个,不是1个,首先在字符串池中创建一个5687的对象,之后再队内存中创建一个String对象,再把5678对象赋值给String对象//这里是两个对像,楼上的全错了不要被误导.
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
这是String带参数的构造方法,需要传一个String对象进行值和hashcode的复制,所以是两个
第四部
String s4 = new String ("5678");到字符串池中找,存在5678对象,再在堆中创建一个新的String对象再把5678复制给新的String对象//由于字符串池中有5678不需要在创建新的了,所以这里只创建了一个对象
综上所述,第一步创建了一个对象,第二步没创建对象,第三部创建了两个对象,第四步创建了一个对象 1+0+2+1=4;所以总共创建了4个对象,请楼主明察追问
首先第一步
String s1 = "1234";时在字符串池中创建了一个1234的对象,指向s1;//这里创建了一个对象
第二步
String s2 ="1234";是先到字符串池中去找,池中有一个1234的对象,直接指向s2;//这里用的是已经有的对象所以并没有重新创建对象,目前还是创建一个对象
第三部
String s3 = new String ("5678");这里创建了两个对象,千万别想错了,是两个,不是1个,首先在字符串池中创建一个5687的对象,之后再队内存中创建一个String对象,再把5678对象赋值给String对象//这里是两个对像,楼上的全错了不要被误导.
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
这是String带参数的构造方法,需要传一个String对象进行值和hashcode的复制,所以是两个
第四部
String s4 = new String ("5678");到字符串池中找,存在5678对象,再在堆中创建一个新的String对象再把5678复制给新的String对象//由于字符串池中有5678不需要在创建新的了,所以这里只创建了一个对象
综上所述,第一步创建了一个对象,第二步没创建对象,第三部创建了两个对象,第四步创建了一个对象 1+0+2+1=4;所以总共创建了4个对象,请楼主明察追问
那这里的s1、s2、s3、s4是不是都不是对象?只是指向对象的引用?而“1234”和“5678”是对象
追答s1 s2 s3 s4都是对象的引用其存放位置是内存中的栈,而真正的对象存放在堆中.s1 s2 s3 s4其实和int i不就是一回事吗,不过int属于基本类型而已.而"1234"或者"5678"在解析器解析时先创建一了一个对象(String s = new String() 只是这里是空的)再用数组一个字符一个字符的加进去而已,所以当你无论在什么地方第一次写"1234"或者"5678"是就已经创建了一个对象,而String s4 = new String ("5678")时只是把字符串池中的"5678"的值赋给新的s4而已
本回答被提问者和网友采纳第2个回答 2013-11-07
3个对象
s1和s2都指向“1234” 当实例化第二个对象s2时 会先从常量池里去找 会找到开始创建的s1指向的“1234” 从而让s2 也指向这个对象 当然,这里说指向不太准确了 java没有指针
只要是new 关键字 它就会去创建新的对象 s3 和s4 只是所指向的String对象的值相等 但是他们不是同一个对象 所以一共创建了3个对象 是否创建新的 可以根据new区分的
s1和s2都指向“1234” 当实例化第二个对象s2时 会先从常量池里去找 会找到开始创建的s1指向的“1234” 从而让s2 也指向这个对象 当然,这里说指向不太准确了 java没有指针
只要是new 关键字 它就会去创建新的对象 s3 和s4 只是所指向的String对象的值相等 但是他们不是同一个对象 所以一共创建了3个对象 是否创建新的 可以根据new区分的