java中的String 类型

windaway 2004-07-23 10:10:33
关于String类型,有几个问题请问大家:

1.String s1 = "aaaa";
String s2 = "aaaa";
System.out.println("s1 == s2 is " + (s1==s2));
显示结果为true;

String s11 = new String("aaaa");
String s22 = new String("aaaa");
System.out.println("s11 == s22 is " + (s11==s22));
显示结果为false;
问题:
String s1 = "a";与String s1 = new String("a");有什么区别?


2。Java里面,对于基本数据类型变量,都是传递值的,而对于对象和数租都是传递引用的。那么String类型应该属于对象吧,可是他确实传递值的,这是为什么?

public class Test1
{
public static void main( String args[])
{
Test1 t = new Test1();
String s1 = new String("aaa");
System.out.println("1: "+s1);
t.setValue(s1);
System.out.println("3: "+s1);
}
void setValue(String s)
{
s = "bbb";
System.out.println("2: "+s);
}
}
结果:1: aaa
2: bbb
3: aaa

但是StringBuffer就是传递引用的
public class Test1
{
public static void main( String args[])
{
Test1 t = new Test1();
StringBuffer s1 = new StringBuffer("aaa");
System.out.println("1:"+s1);
t.setValue(s1);
System.out.println("3: "+s1);
}
void setValue(StringBuffer s)
{
s.replace(0,s.length(),"bbb" );
System.out.println("2: "+s);
}
}
结果:1: aaa
2: bbb
3: bbb

问题:这个如何解释呢?谢谢

...全文
4685 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
wpx80 2004-07-29
  • 打赏
  • 举报
回复
zhengkan(十大杰出神仙) 说得对
java不会在栈内分配对象
kaiserfeng 2004-07-29
  • 打赏
  • 举报
回复
学习中,Thinking in java 里面说得很清楚.
zhengkan 2004-07-27
  • 打赏
  • 举报
回复
faint看了半天一半说的对一半说的是错的根本在误人子弟
j2nix 2004-07-27
  • 打赏
  • 举报
回复
强烈建议对String类型有不彻底明白的,多去了解JVM及相关更深层的内容,如:常量池等。

这才是解决这个老生长谈的问题的根本。
langxiaofeng 2004-07-27
  • 打赏
  • 举报
回复
String和StringBuffer都是string的子类
langxiaofeng 2004-07-27
  • 打赏
  • 举报
回复
String的值是不能改变的,StringBuffer的值才能被改变的,
equset比较值,==是比较地址.
hsdxhc 2004-07-27
  • 打赏
  • 举报
回复
总算明白了一些。
windaway 2004-07-27
  • 打赏
  • 举报
回复
呵呵,我现在总结一下:
在传递值时,参数值得内容不会因为在函数内变化了而变化;在传递引用的时候,如果该变量所值的内容发生了变化,则相应的内容会发生变化,如果只是把变量所指的地址发生了变化,那么函数返回时该变量所对应的地址还是以前的
下面这个例子可以说明这个问题:
public class Test
{ public int i, j,
public void test_m( Test a)
{ test5 b = new Test();
b.i = 1;
b.j = 2;
a = b;
}
public void test_m1( Test a )
{ a.i = 1;
a.j = 2;
}
public static void main(String argv[])
{ Test t= new Test();
t.i = 5;
t.j = 6;
System.out.println("t.i = "+ t.i + " t.j= " + t.j);
t.test_m(t);
System.out.println("t.i = "+ t.i + " t.j= " + t.j);
t.test_m1(t);
System.out.println("t.i = "+ t.i + " t.j= " + t.j);
}
}
函数test_m是在函数内改变了该参数的地址,并没有改变该参数所指的内容,所以,函数返回时恢复以前所指向的地址,显示得还是以前的内容;
函数test_m1是在函数内改变了该参数所对应的内容,所以函数返回时指向以前的地址,此时,该地址的内容已经发生变化了,显示得是改变后的内容。
hl_longman 2004-07-27
  • 打赏
  • 举报
回复
好帖,顶一把
zhengkan 2004-07-27
  • 打赏
  • 举报
回复
楼上练内功的,其实"aaaa"这种也不是放在栈里的吧,由于string比较特殊,jvm会管理一个string pool,你可以注意一下string有一个intern的方法,这种string,jdk的帮助文档里明确说明是默认intern的,intern之后会被放进字符串pool里面,也不是在栈上分配的
dxyjb2000 2004-07-27
  • 打赏
  • 举报
回复
有的回答根本就是错误的
string a="aaaa"
这么定义的a根本不叫句柄,而叫做非句柄变量,指向的不是一个堆地址。但是他所在的地方都是栈,因为string是常用的主类型,所以为了简便调用要放到栈而不是堆里。

java里的对象都是由new或者返回一个对象的方法来定义的,每用1个new就生成一个新对象
String a=new String("aaaa")
这个a才叫指向对象的句柄,比较句柄实际是比较2个句柄所指的堆内存,就算保存的内容一样,但地址肯定是不一样的。
LIANGQIAN1984 2004-07-27
  • 打赏
  • 举报
回复
我也是刚学,你可以去买本thinking in java

wpx80 2004-07-23
  • 打赏
  • 举报
回复
再来考就StringBuffer,比较一下StringBuffer和String的两个成员函数,JDK源码
String:
public String replace(char old,char new) {
.......
while (++i < len) {
if (val[off + i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];//注意这里,在成员方法的局部栈空间内,
构造一个String中char序列的副本,并无
修改自身的成员"private char[] val"
for (int j = 0 ; j < i ; j++) {
buf[j] = val[off+j];
}
while (i < len) {
char c = val[off + i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(0, len, buf);
}

StringBuffer:
public synchronized StringBuffer append(String str) {
if (str == null) {
str = String.valueOf(str);
}

int len = str.length();
int newcount = count + len;
if (newcount > value.length)
expandCapacity(newcount);
str.getChars(0, len, value, count);//注意这里,新加入的str被切实
加到StringBuffer自身的成员
"private char[] value"中
count = newcount;
return this;//这是为了支持诸如a.append().append()的链式调用
}

这就是为什么StringBuffer的修改函数能起修改传入对象的作用
wpx80 2004-07-23
  • 打赏
  • 举报
回复
dlxu(沿着Java继续前进) 是对的
下面一例子
public class Test {
public static void test(String str) {
str = "World";
}
public static void main(String[] args) {
String string = "Hello";
test(string);
System.out.println(string);
}
}
输出是:Hello
但是其实String类型依然是传引用的,一切模糊来自String支持"="
main函数中假设string是一个String对象的地址引用,假设值为0xccef
调用test(string)时将string的值入栈,在test中它被指向另一个"World"串,这个引用
指向另一地址,但是在返回时所有入栈参数会Pop,string的地址值会恢复
windaway 2004-07-23
  • 打赏
  • 举报
回复
那对于StringBuffer类型来说如何解释呢?谢谢
dlxu 2004-07-23
  • 打赏
  • 举报
回复
第二个问题,其实传递对象的时候也是传值的,只不过这个值是对象的一个引用而已,所以你参数为String s1时,传递了s1引用的一份拷贝。当你重新在子函数中使用s="bbb"的时候,只是把s1的引用的那份拷贝重新指向了新的地址,原来s1还是"aaa"字符串的一个引用并没有变化,明白否?
windaway 2004-07-23
  • 打赏
  • 举报
回复
那关于第二个问题如何解释呢?谢谢
wpx80 2004-07-23
  • 打赏
  • 举报
回复
apple21(编姑娘的小花篮) 的回答是正解
simon160984 2004-07-23
  • 打赏
  • 举报
回复
我也发表一下意见:)
其实
String s1 = "aaaa";
String s2 = "aaaa";
等价于
String st = new String("aaaa");
String s1 = st;
String s2 = st;
这样好理解XioSan的解释了吧!
likeBean 2004-07-23
  • 打赏
  • 举报
回复
纠正一下,是我搞错了
apple21(编姑娘的小花篮)说的挺对的啊,a==b比较的是地址,
String s1 = "aaaa";
String s2 = "aaaa";
jvm会分配一块地址给"aaaa",然后然s1和s2都指向这块地址,所以返回的是true;
String s11 = new String("aaaa");
String s22 = new String("aaaa");
jvm会给s11和s22各分配一块地址,所以返回的是false;

这是java语法的问题,所以没有为什么的答案,只有说java编译器就是这么干的,详细的
你可以参考java tutorial,说的很清楚。
加载更多回复(16)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧