A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Miss小强 中级黑马   /  2013-4-30 09:14  /  2564 人查看  /  21 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Miss小强 于 2013-5-1 18:16 编辑

(4)    指出下列程序运行的结果,并说明主要原因

public class Example {

String str = new String(“good”);

char[] ch = {‘a’,'b’,'c’};

public static void main(String[] args) {

Example ex = new Example();

ex.change(ex.str, ex.ch);

System.out.print(ex.str+”   and   “);

System.out.print(ex.ch);

}

public void change(String str,char ch[]){

str = “test ok”;

ch[0]=’g';

}

}

评分

参与人数 1技术分 +1 收起 理由
曹睿翔 + 1 很给力!

查看全部评分

21 个回复

倒序浏览
运行结果 知道  good gbc
可是这是为什么呢??
回复 使用道具 举报
这是因为你定义的str和char[] ch是全局变量,在执行ex.change(ex.str, ex.ch);后确实把它们的值互换了,但下一步中System.out.print(ex.str+"   and   ");

System.out.print(ex.ch);调用的还是原全局变量,跟你之前change函数没关系。
回复 使用道具 举报
liuelxiwd 发表于 2013-4-30 09:54
这是因为你定义的str和char[] ch是全局变量,在执行ex.change(ex.str, ex.ch);后确实把它们的值互换了,但下 ...

那为什么ch的值又变了?
回复 使用道具 举报
用一句话来说:change函数里的str前面如果加上this,就和你想的结果一样了。
回复 使用道具 举报
突然发现这个程序很有意思。 我上面的说法虽然结果上没有问题。但也同样没有说明问题的原因。
我回头来看的时候,发现我也并没有理解。然后又仔细运行和思考:
分析如下,看代码注释和下面的解说(这是我的理解,期待来高手有不同看法):
  1. public class Example
  2. {

  3.         String str = "good";

  4.         char[] ch = {'a','b','c'};

  5.         public static void main(String[] args)
  6.         {

  7.                 Example ex = new Example();

  8.                 ex.change(ex.str, ex.ch);

  9.                 System.out.print(ex.str+"   and   ");
  10.                
  11.                 System.out.println(ex.ch);
  12.                
  13.                 System.out.println(ex);   //打印ex的地址

  14.         }

  15.         public void change(String str,char ch[])
  16.         {
  17.                 System.out.println(str);    //打印str。结果为good。
  18.                 System.out.println(str==this.str);  //第一个str与this.str判断
  19.                 str = "test ok";
  20.                 System.out.println(this);    //打印this地址
  21.                 System.out.println(str==this.str);    //第二个str与this.str判断

  22.                 ch[0]='g';

  23.         }

  24. }
复制代码
ex和this的地址,每次运行都一样。
第一个str与this.str判断返回true,第二个str与this.str判断返回false。
这说明ex和this是同一个对象,change函数里的str,没赋值前是同一个对象,赋值后变成了不同的对象。
这说明什么呢?
String有一个特性,有一个常量池。String s = new String("good");也有一个特性,叫这里实际是两个对象。
change函数中,String str实际上就已经声明了对象。
这样是不是全都可以理解了。

评分

参与人数 1技术分 +1 收起 理由
曹睿翔 + 1 赞一个!

查看全部评分

回复 使用道具 举报
我做了几个实验,可以跟c语言中传递参数思考了一下,在change函数中str是局部变量在参数传递中是把成员变量str的值传递过去了就是good而不是str的句柄,那么此处就相当于str=“good”;然后把str的值改变为test ok;这些都是在栈中进行的,并没有传递到堆中,数组的传递中是传递的句柄,那么对引用的改变就是对原有数组的改变,
希望对你有帮助;
回复 使用道具 举报
xiewen 中级黑马 2013-4-30 16:25:40
8#
java里方法的参数传递方式只有一种:至传递。所谓值传递,就是将实际参数值的副本(复制品)传入方法内,而参数本身不会受到任何影响。ch[0]是一个引用地址,它把引用地址指向的值改变了,所以ch数组改变了
回复 使用道具 举报
本帖最后由 曾德强 于 2013-4-30 18:48 编辑

这个问题对理解字符串很有帮助,也挺有意思的;首先得理解字符串为引用类型,并且是不可改变的,其次,字符是基本类型(值类型);当然字符数组是引用类型,但是其里面的每个元素都是值类型的(理解这点很重要);在传参时大家都知道,只是传了一个有关类型的副本;
public void change(String str,char ch[]){

str = “test ok”;

ch[0]=’g';

}
对于这个方法,有两个引用类型的参数;str接收的是存放“good”字符串内存地址的副本;ch接收的是存放ch字符数组内存的副本;但是有一点,在change()函数里面对str="text ok";由于string类型的值是不可改变的,相当于在内存里又开辟了一块内存空间存放"test ok";并把相应的地址赋给str;但是这并没有改变主函数里面的str所存放的地址,因为传给change()函数的仅仅是一个“good”内存地址的副本;故string类型的值还是没有改变;
而对于char[]而言;里面的每个元素都是值类型;在change()函数里面对ch[0]='g';覆盖了原来ch[0]里面的值;所以,在主函数里面char[]数组里面的值发生了变化;
关于字符串可以参考:http://bbs.itheima.com/thread-48113-1-1.html

评分

参与人数 1技术分 +1 收起 理由
曹睿翔 + 1 赞一个!

查看全部评分

回复 使用道具 举报
如果仍有问题,请继续追问,如果问题已解决,请将分类改为已解决,谢谢
回复 使用道具 举报
黑马伍哲沂 发表于 2013-4-30 14:04
突然发现这个程序很有意思。 我上面的说法虽然结果上没有问题。但也同样没有说明问题的原因。
我回头来看的 ...

突然之间想明白了如果在change方法中加入这么一句话
this.str=str;
就是test ok了
谢谢哥们了。。从你的程序里得到了启发
但是你这句   这说明ex和this是同一个对象,change函数里的str,没赋值前是同一个对象,赋值后变成了不同的对象。
怎么理解??
回复 使用道具 举报
在change方法中这样输出
System.out.println(str.hashCode());    //打印str。结果为good。
                System.out.println(this.str.hashCode());
                System.out.println(str==this.str);  
                //第一个str与this.str判断
                str = "test ok";
                System.out.println(this.str.hashCode());
                System.out.println(str.hashCode());

就一目了然了。。。多谢六楼的哥们了
回复 使用道具 举报
Miss小强 发表于 2013-5-1 17:56
突然之间想明白了如果在change方法中加入这么一句话
this.str=str;
就是test ok了
  1. public void change()
  2.                 {
  3.                         String str = ex.str;    //就是一个成员变量与局部变量的问题。用this。
  4.                         str = "test ok";        //局部str变成赋值后的。成员str没有变。
  5.                         char ch[] = ex.ch;
  6.                         ch[0] = 'g';
  7.                 }
复制代码
用无参来写这个change,我是以上理解。

回复 使用道具 举报
查下api 吧,string 是不可变的、
回复 使用道具 举报
黑马伍哲沂 发表于 2013-5-1 20:14
用无参来写这个change,我是以上理解。

能不能详细说一下在内存中的存储流程。
回复 使用道具 举报
这道题我是这么理解的,首先这个对象创建Example ex = new Example();语句一执行,类Example被加载,执行String str = new String(“good”);语句,这里有一点需要注意,就是String 是一个类,所以全局变量str里存储一个地址值,也就是字符串good在堆内存中的位置。ex对象被创建后,栈内存中已经存在变量str了,当调用change()方法时,方法中的局部变量str虽然被声明并且赋值,但是并没有加载进ex所指向的那个对象的栈内存(假如是因为里面已经存在了一个相同名称的变量,并且这个变量里边存的是一个地址值。否则解释不通,这里希望和大家探讨),而字符型数组ch被加载进去了,所以打印的是 good gbc。当在change()函数中加入this.str=str;这条语句后,ex所指向的那个对象中的str值被修改了,打印结果自然就不一样了。
回复 使用道具 举报
王廷顺 发表于 2013-5-2 17:49
这道题我是这么理解的,首先这个对象创建Example ex = new Example();语句一执行,类Example被加载,执行St ...

看过你的描述,感觉不太理解你的说法。我把我的理解上图吧。

未命名.jpg (36.56 KB, 下载次数: 0)

未命名.jpg
回复 使用道具 举报
黑马伍哲沂 发表于 2013-5-2 18:45
看过你的描述,感觉不太理解你的说法。我把我的理解上图吧。

你的意思是局部变量str要想被赋值,在change函数中必须是使用this才可以,是因为全局变量str现在指向的是good吗。ex.change(ex.str, ex.ch);语句执行后,在
public void change(String str,char ch[]){

str = “test ok”;

ch[0]=’g';

}
函数中String str = ex.str;(good在内存中的地址值赋给了局部变量str)。接下来str = "test ok";语句执行,但是"test ok"并没有被赋给str(否则就不会输出good)。执行到这里,问题出现了,str是一个还是两个,他们在内存中的存储又是怎样的。还有你说String有一个特性,有一个常量池。具体能说说是怎么回事吗,是不是String 这个特性能解决我上边的那个疑问呢。
回复 使用道具 举报
王廷顺 发表于 2013-5-3 15:53
你的意思是局部变量str要想被赋值,在change函数中必须是使用this才可以,是因为全局变量str现在指向的是 ...

前面应该是我理解错了吧。
这里一直就是两个str。一个叫this.str,一个叫str。这两个是不同的。
再给你看个更经典的代码,你就明白了(我的这个理解)。
  1. class Person
  2. {
  3.         String name;
  4.         public void setName(String name)
  5.         {
  6.                 this.name =name;
  7.         }
  8. }
复制代码
另外,关于静态池。你要是不知道这一块,就搜索下相关资料自己去看看。
不知道你学到哪了。后面会讲到享元设计模式。String里面有这么个东西。(我暂时是认为这里是享元设计模式,还得看以后知识的积累再验证)。


回复 使用道具 举报
本帖最后由 王廷顺 于 2013-5-3 21:19 编辑

哥们,还是你理解的深入,我好像明白了。非常感谢你的解答{:soso_e181:}。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马