面视题:下面代码将输出什么结果

yantao1982 2008-06-22 02:23:37
package com.test;

public class Test {


public static void main(String[] args) {
String a = "abc";
String[] b = {"a","b","c"};
change(a,b);
System.out.println(a);
System.out.println(b[0]+b[1]+b[2]);
}

public static void change(String a,String[] b){
a="123";
b[0]="A";
}

}






结果是:
abc
Abc


请问为什么String a 的值没被改变,而数字 b[0]的值却改变了??
...全文
216 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
meisongzhu 2008-06-25
  • 打赏
  • 举报
回复
12,13楼的完全正确!!!!!
我稍微修改了下这个程序,可以看到在被调用的方法中对象a和b[]在堆中地址的变化。
可以说在change中的参数a,b[]都是局部变量,只是一开始是引用了外层方法中分配的对象,只要对a,b[]重新赋值就等于重新申请了新的堆空间给新的变量,既"123"这个字符串对象是在堆中重新申请了地址空间,之后又把局部变量a的引用改到了"123",所以在a被重新赋值前后其地址是变化了的。原程序等价于:
public class Test { 
public static void main(String[] args) {
String a = "abc";
String[] b = {"a","b","c"};
change(a,b);
System.out.println(a);
System.out.println(b[0] + b[1] + b[2]);
}

private static void change(String a,String[] b){
String temp = "123";
a = temp;
b[0] = "A";
}
}

####################################################################################

我用来验证地址变化情况的程序如下(写得不够简洁,大家见笑了):
public class Test { 
public static void main(String[] args) {
System.out.println("In main() ");
String a = "abc";
Addr ad = new Addr(a);
ad.retAddr("a");
String[] b = {"a","b","c"};
ad = new Addr(b);
ad.retAddr("b[]");
ad = new Addr(b[0]);
ad.retAddr("b[0]");
ad = new Addr(b[1]);
ad.retAddr("b[1]");
ad = new Addr(b[2]);
ad.retAddr("b[2]");
change(a,b);
System.out.println(a);
System.out.println(b[0] + b[1] + b[2]);
}

private static void change(String a,String[] b){
System.out.println("\nenter change ");
Addr aod = new Addr(a);
aod.retAddr("a");
aod = new Addr(b);
aod.retAddr("b[]");
aod = new Addr(b[0]);
aod.retAddr("b[0]");
aod = new Addr(b[1]);
aod.retAddr("b[1]");
aod = new Addr(b[2]);
aod.retAddr("b[2]");
System.out.println("a = " + a);
System.out.println("b[] = " + b[0] + b[1] + b[2]);
a = "123";
System.out.println("\nreset a");
System.out.println("a = " + a);
aod = new Addr(a);
aod.retAddr("a");
b[0] = "A";
aod = new Addr(b);
aod.retAddr("b[]");
aod = new Addr(b[0]);
aod.retAddr("b[0]");
aod = new Addr(b[1]);
aod.retAddr("b[1]");
aod = new Addr(b[2]);
aod.retAddr("b[2]");
System.out.println("\nreset b[]");
System.out.println("b[] = " + b[0] + b[1] + b[2]);

System.out.println("exit change!\n");
}

private static class Addr {
public Addr(Object o) {
aObj = o;
}

public void retAddr(String s) {
System.out.print("&" + s + " = ");
System.out.println("@" + Integer.toHexString(aObj.hashCode()));
}

private Object aObj;
}

}


运行结果:
In main()
&a = @17862
&b[] = @c17164
&b[0] = @61
&b[1] = @62
&b[2] = @63

enter change
&a = @17862
&b[] = @c17164
&b[0] = @61
&b[1] = @62
&b[2] = @63
a = abc
b[] = abc

reset a
a = 123
&a = @be32
&b[] = @c17164
&b[0] = @41
&b[1] = @62
&b[2] = @63

reset b[]
b[] = Abc
exit change!

abc
Abc

############################################################################################

我们还可以做个这样的测试:
public class Test { 
public static void main(String[] args) {
String a = "abc";
String[] b = {"a","b","c"};
change(a,b);
System.out.println(a);
System.out.println(b[0] + b[1] + b[2]);
}

private static void change(String a,String[] b){
a = "123";
String[] temp = {"1","2","3"};
b = temp;
b[0] = "A";
}
}

看看结果是不是:
abc
abc



lord_is_layuping 2008-06-23
  • 打赏
  • 举报
回复
12,13楼正解。



qinqinhao 2008-06-23
  • 打赏
  • 举报
回复
ding
mark
bananabear 2008-06-23
  • 打赏
  • 举报
回复
String 类对象是 final 的,这种类的对象的值是不可以改变的,要想改变的话只有重新赋值。
例如:
String a = "a";
项把a的值改成 "b";
只有一种方法:a = "b";没有其他任何方法。

建议楼主看看final 类的定义和使用。Java库中有很多都是final类,例如Integer
becloud 2008-06-23
  • 打赏
  • 举报
回复

package com.test;
public class Test {
public static void main(String[] args) {
//这里引用a指向对象"abc"
String a = "abc";
String[] b = {"a","b","c"};
//调用方法
change(a,b);
System.out.println(a);
System.out.println(b[0]+b[1]+b[2]);
}
public static void change(String a,String[] b){
//这里的引用a首先指向对象"abc",接着又会指向对象"123",以前那个"abc"仍然被main方法中的a所指向,所以那个a会打印出"abc"
a="123";
//b[0]指向"a",b[1]指向"b",b[2]指向"c",接着b[0]又会指向"A",以前指向的那个"a"在以后的某个时刻会被GC回收掉,所以b[0]+b[1]+b[2]会打印出Abc
b[0]="A";
}
}
mimixikou 2008-06-23
  • 打赏
  • 举报
回复
String 不是个对象吗?对象不是按地址传递的吗?
怎么到这里又按值传递了?
有没有高人给解释下啊
gongyali2005 2008-06-22
  • 打赏
  • 举报
回复
这就是所谓的值传递,和引用传递的区别!

当然,STRING是个特殊的家伙,
rosewj 2008-06-22
  • 打赏
  • 举报
回复
JAVA中没有按值传递的 所以这一类的传递都不会实现
icyice1989 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 ZangXT 的回复:]
上面的解释有问题,java中没有传地址的概念。
在Thinking in Java中有这样的例子:
so if you want to hold a word or sentence ,you create a String reference:
String s;
也就是说s是一个reference;当把s做为参数的时候,
比如public void static change (String ss){
ss=new String("abc");
}
change(s);
传进去的是reference s的一个副本。你对ss的任意操作都不会改变外部s指向的对象.其实数组也一样,楼主的例子中…
[/Quote]
12楼正解!
harkue 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 KOOK_OKKO 的回复:]
Java中只有基本数据类型,比如int、double、boolean等是值传递,其他一律是引用传递
对象传递给函数时传递的是新的引用。
应为String改变的是新的引用,所以a不变

应为String[]改变的是新引用指向的值b[0],所以改变

[/Quote]

同意!
KOOK_OKKO 2008-06-22
  • 打赏
  • 举报
回复
Java中只有基本数据类型,比如int、double、boolean等是值传递,其他一律是引用传递
对象传递给函数时传递的是新的引用。
应为String改变的是新的引用,所以a不变

应为String[]改变的是新引用指向的值b[0],所以改变
qq278095755 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 yeezai 的回复:]
java只按引用(也就是你说的地址)传递,绝不会按值传递的
a="123";//改变了a的引用
b[0]="A"; //b的引用没有改变,只是改变了引用指向的对象
[/Quote]
javatotheworld 2008-06-22
  • 打赏
  • 举报
回复
不是很清楚啊,学习了,还有人好好解释下吗
ZangXT 2008-06-22
  • 打赏
  • 举报
回复
那些认为数组是传地址的可以看看这个例子:
public class Test {
public static void change(String[] s){
s[0]="t";
s=new String[10];
for(int i=0;i<s.length;i++){
s[i]=String.valueOf(i);
}
}
public static void main(String[] args) {
String[] s={"a","b","c"};
System.out.println(s[0]+s[1]+s[2]);
change(s);
System.out.println("After changing.....");
System.out.println(s[0]+s[1]+s[2]);
for(int i=0;i<s.length;i++){
System.out.print(s[i]);
}
System.out.println();

}
}
输出:
abc
After changing.....
tbc
tbc
ZangXT 2008-06-22
  • 打赏
  • 举报
回复
上面的解释有问题,java中没有传地址的概念。
在Thinking in Java中有这样的例子:
so if you want to hold a word or sentence ,you create a String reference:
String s;
也就是说s是一个reference;当把s做为参数的时候,
比如public void static change (String ss){
ss=new String("abc");
}
change(s);
传进去的是reference s的一个副本。你对ss的任意操作都不会改变外部s指向的对象.其实数组也一样,楼主的例子中,如果让b=一个新的数组,外边的数组同样不受影响 ,这里关键的问题是你通过b[0],引用了b所指向的实际对象,当然对象的值会改变了.
下面举个这样的例子:
public class Test {
public static void change(StringBuffer buffer){
buffer.append("world");
buffer=new StringBuffer("no effect!");
}
public static void main(String[] args) {
StringBuffer s=new StringBuffer("Hello ");
System.out.println(s);
change(s);
System.out.println(s);
}
}
输出是 :
Hello
Hello world
很明显,buffer.append()是 对外面引用的对象的操作,所以产生作用,而buffer=new StringBuffer("no effect!")是对buffer这个值的改变,对外面没有影响.
jingulang 2008-06-22
  • 打赏
  • 举报
回复
明白了

change方法只是把传参进去的a初始话为123 跟main方法里的String a 毫无关系。。。。





yeezai 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 Mailbomb 的回复:]
因为字符串是按值传递,而数组是按址传递
[/Quote]
java只按引用(也就是你说的地址)传递,绝不会按值传递的
a="123";//改变了a的引用
b[0]="A"; //b的引用没有改变,只是改变了引用指向的对象
JAVA资料太多?选中想收藏的文字(图片),右键选“收录到易载”,搞定!
hunsilj 2008-06-22
  • 打赏
  • 举报
回复
public static void change(String a,String[] b){
a="123";
b[0]="A";
}

通俗点解释: change函数,对于普通变量a,改变的是a的副本,此副本为change中的局部变量,而对于传过来的数组(或地址)b则是在原来的变量上操作。
GMSUN333 2008-06-22
  • 打赏
  • 举报
回复
请高淫吧 我是来学习的
ryan0629 2008-06-22
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 Mailbomb 的回复:]
因为字符串是按值传递,而数组是按址传递
[/Quote]

就是这样

传得是"abc"这个字符串

不妨将方法里的a换名为s
"abc"传进来,s="abc",然后,s="123",这里操作的只是方法里的s,由始至终a都没有变,始终都是指向"abc"这个串

注意,s="123"不是更改字符串"abc"为"123",而是将s指向另外一个字符串"123",如果"123"这个串不存在,就创建这个字符串
加载更多回复(5)

62,614

社区成员

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

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