问题1:在判断两个String 是否相等的时应该用equals()函数 以为==只能检测到两个String是否是同一地址(公用)所以String s1 = "aaaa";
String s2 = "aaaa";是true; (“aaaa”放在一个地址里 s1和s2同指向一个地址)String s11 = new String("aaaa");
String s22 = new String("aaaa");不是在同一地址里
String s2 = "aaaa";是true; (“aaaa”放在一个地址里 s1和s2同指向一个地址)String s11 = new String("aaaa");
String s22 = new String("aaaa");不是在同一地址里
你没有理解 "aaa" 是什么!
其实在Java中 "aaa" 就是String类的一个实例,它是有地址的。String s1;
s1 = "aaa";
只是将"aaa"的地址传给s1.
String s2 = "aaaa";
System.out.println("s1 == s2 is " + (s1==s2));
显示结果为true;不肯能是true的,返回的是false。
那么第2个问题如何解释呢?
to: likeBean(喜欢吃咖啡豆)
我是在Jbuildx里测试的,上面的所有代码我都测试了的
你也可以测试以下
to:XioSan(Milo)
不太明白你的解释,可否详细一些?
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,说的很清楚。
其实
String s1 = "aaaa";
String s2 = "aaaa";
等价于
String st = new String("aaaa");
String s1 = st;
String s2 = st;
这样好理解XioSan的解释了吧!
下面一例子
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的地址值会恢复
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的修改函数能起修改传入对象的作用
他被来传进来的是引用,然后又被"bbb"覆盖了。
自己去琢磨吧。
public StringBuffer replace(int start,int end,String str)来覆盖给定的地址内容。
"\"" // a string containing " alone
"This is a string" // a string containing 16 characters
"This is a " + // actually a string-valued constant expression,
"two-line string" // formed from two string literals
Because Unicode escapes are processed very early, it is not correct to write "\u000a" for a string literal containing a single linefeed (LF); the Unicode escape \u000a is transformed into an actual linefeed in translation step 1 (§3.3) and the linefeed becomes a LineTerminator in step 2 (§3.4), and so the string literal is not valid in step 3. Instead, one should write "\n" (§3.10.6). Similarly, it is not correct to write "\u000d" for a string literal containing a single carriage return (CR). Instead use "\r". Each string literal is a reference (§4.3) to an instance (§4.3.1, §12.5) of class String (§4.3.3). String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions (§15.28)-are "interned" so as to share unique instances, using the method String.intern.
Thus, the test program consisting of the compilation unit (§7.3): package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }and the compilation unit:package other;
public class Other { static String hello = "Hello"; }produces the output:true true true true false trueThis example illustrates six points:1.Literal strings within the same class (§8) in the same package (§7) represent references to the same String object (§4.3.1).
2.Literal strings within different classes in the same package represent references to the same String object.
3.Literal strings within different classes in different packages likewise represent references to the same String object.
4.Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
5.Strings computed at run time are newly created and therefore distinct.
6.The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.
在传递值时,参数值得内容不会因为在函数内变化了而变化;在传递引用的时候,如果该变量所值的内容发生了变化,则相应的内容会发生变化,如果只是把变量所指的地址发生了变化,那么函数返回时该变量所对应的地址还是以前的
下面这个例子可以说明这个问题:
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是在函数内改变了该参数所对应的内容,所以函数返回时指向以前的地址,此时,该地址的内容已经发生变化了,显示得是改变后的内容。
equset比较值,==是比较地址.
string a="aaaa"
这么定义的a根本不叫句柄,而叫做非句柄变量,指向的不是一个堆地址。但是他所在的地方都是栈,因为string是常用的主类型,所以为了简便调用要放到栈而不是堆里。java里的对象都是由new或者返回一个对象的方法来定义的,每用1个new就生成一个新对象
String a=new String("aaaa")
这个a才叫指向对象的句柄,比较句柄实际是比较2个句柄所指的堆内存,就算保存的内容一样,但地址肯定是不一样的。
java不会在栈内分配对象