黑马程序员技术交流社区

标题: 关于传值的问题 [打印本页]

作者: jiangyutc    时间: 2014-3-27 21:23
标题: 关于传值的问题

请问这道题的答案为什么是B
请详细解答
非常感谢!!

作者: linweiwen    时间: 2014-3-27 21:47
str字符串和ch字符数组都是Example这个类的成员变量,
然后对结果产生影响的,就是change这个方法,
把str传进去,它的内容整个从"good"变成"test ok"了;
然后ch则只改变ch[0],‘a’变为‘g’。
然后两条输出命令都没有换行,中间加了个and连接,
所以答案就是B了。

其实你只要知道成员变量的一些用法,就能知道答案了。


作者: Zero霖    时间: 2014-3-27 21:49
本帖最后由 Zero霖 于 2014-3-27 21:53 编辑

因为change方法中的参数str跟Example类的成员变量str不是同一个变量,换句话说,你把change方法中的参数str改成s,以及参数ch改成c的结果也是一样。假如我们换成public void change(String s,char[] c)这样估计你就看的懂了。ex.change(ex.str,ex.ch)只是将"good"对象地址传递给s,以及将数组对象地址传递给c,这样s指向了“good”对象,而c指向的是数组ch的对象地址。当s="test ok"时,只是改变了s的指向,s指向了"test ok"这个对象,而成员变量str仍然指向的是"good",成员变量str的指向并没有更改。而c指向的是数组ch的对象地址,当c[0]='g'时,相当于将数组ch[0]的元素值给改变了,ch[0]的值就被改成了'g'。故此时,str指向的是对象"good",而数组ch中的元素集是{'g','b','c'}。输出的就是B。值得一提的是,字符串一旦被创建,就不能被改变,也可以称字符串为字符串常量。普及一下,String s="good";s="cool";这句话并没有修改字符串"good"的值,而只是让变量s的指向由"good"转向了"cool","good"字符串对象在内存中仍然存在,只是没有变量指向它,再不定时的时候,JVM的垃圾回收器会将其回收。
作者: Zero霖    时间: 2014-3-27 21:54
linweiwen 发表于 2014-3-27 21:47
str字符串和ch字符数组都是Example这个类的成员变量,
然后对结果产生影响的,就是change这个方法,
把str ...

你说的有些不对吧,并不是str的内容改变了,而是它的指向变了,这可不能误导哦……
作者: 李海霞java    时间: 2014-3-27 22:18
String字符串常量一旦被初始化就不会变,所以程序初始化str为good是不会变的。而change方法改变了Example中数组角标为0的元素,由a变成了g(数组角标是从0开始的),所以结果是B
作者: 海世山盟    时间: 2014-3-27 23:29
我记得String类型很是特殊。一旦一个句柄对应的存储空间有了非空值后,这个值就会一直存在于内存中,当再对该句柄进行操作的时候,系统会直接跳过。
作者: linweiwen    时间: 2014-3-27 23:50
Zero霖 发表于 2014-3-27 21:54
你说的有些不对吧,并不是str的内容改变了,而是它的指向变了,这可不能误导哦…… ...

你说得对,我的表述不太严谨,谢谢你的提醒。
作者: 路西法    时间: 2014-3-28 01:01
这道题看上去简单   其实考的是你对变量在内存中分配的理解  还有局部变量和成员变量的区分   我把程序改了一下 你看一下
public class Test{
                String str = new String ("good");
                char [] ch = {'a','b','c'};
               
        public static void main(String[] args) {
                Test ts = new Test();
                ts.change(ts.str,ts.ch);
                System.out.print(ts.str+"and ");
                System.out.print(ts.ch);
        }
        public void change(String str,char ch[]){
                str ="test ok";//改成 str = new String("test ok")在堆内存中存储了“test ok”
                ch[0]='g';
                System.out.print(str+"and  ");//输出结果是test Ok,说明str确实变了
               
                System.out.print(ch);//gbc
        }
}

new String() 和数组 其实都是引用变量   他们是在堆内存中的  而str 和 ch 这两个是在栈内存中的  而字符串是不可变的   这些上面几位已经说过了
我来说一下生存周期的问题  首先得搞清楚 第一个 str 是类变量  而change方法里的str 是局部变量  2个根本不是一个变量   我在change里面的添加的代码
说明 change里面的str是改变了的 并且值也确实是 “test ok” ,那为什么结果是“good”?因为这里1:“test OK”是字符串直接量  定义后放在字符串缓存池里的对堆内存里的没影响 2 这里的str 是局部变量  生命周期随着 change的结束而结束      所以即使在change方法里str变了 但是输出的还是“good”

然后我又试着把str ="test ok";改成 str = new String("test ok")
但是结果还是一样没变 这就说明局部变量str的变化对成员变量压根没影响



作者: ╰青青子佩ˊゝ    时间: 2014-3-28 07:36
还是 Zero霖 的解释更详细具体透彻,佩服!
  1. public class Example {
  2.         String str = new String("good");
  3.         char[] ch = {'a','b','c'};
  4.         public static void main(String[] args) {
  5.                 Example ex = new Example();
  6.                 ex.change(ex.str, ex.ch);
  7.                 System.out.println(ex.str+" and ");
  8.                 System.out.println(ex.ch);
  9.         }
  10.         public void change(String str , char ch[]) {
  11.                 //这个str被当成局部变量,而不是Example中的成员变量
  12.                 //相当于给str这个局部变量赋了"test ok"这个值,并没有改变ex这个对象的成员变量str的值
  13.                 str="test ok" ;
  14.                 //要使得ex中的str也变为"test ok"(即想要让答案为D)的话,应该加上如下一行代码
  15.                 this.str = str ;       
  16.                 ch[0] = 'g' ;
  17.         }       
  18. }
复制代码

       
作者: jiangyutc    时间: 2014-3-28 23:00
Zero霖 发表于 2014-3-27 21:49
因为change方法中的参数str跟Example类的成员变量str不是同一个变量,换句话说,你把change方法中的参数str ...

多谢
很详细
:handshake
作者: 严旭晟    时间: 2014-3-29 09:01
String是final,对String类的任何改变,都返回一个新的String类对象.因此当把String类的引用传递给一个方法,该方法对String的任何改变,对原引用指向的对象没有任何影响,这一点和基本数据类型相似.
分解见图:

传值.jpg (1003.9 KB, 下载次数: 36)

传值.jpg





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2