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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© jiangyutc 中级黑马   /  2014-3-27 21:23  /  1281 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


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

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

10 个回复

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

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

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 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的垃圾回收器会将其回收。

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

回复 使用道具 举报 1 0
linweiwen 发表于 2014-3-27 21:47
str字符串和ch字符数组都是Example这个类的成员变量,
然后对结果产生影响的,就是change这个方法,
把str ...

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

你说得对,我的表述不太严谨,谢谢你的提醒。
回复 使用道具 举报
这道题看上去简单   其实考的是你对变量在内存中分配的理解  还有局部变量和成员变量的区分   我把程序改了一下 你看一下
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的变化对成员变量压根没影响


回复 使用道具 举报
还是 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. }
复制代码

       
回复 使用道具 举报
Zero霖 发表于 2014-3-27 21:49
因为change方法中的参数str跟Example类的成员变量str不是同一个变量,换句话说,你把change方法中的参数str ...

多谢
很详细
:handshake
回复 使用道具 举报
String是final,对String类的任何改变,都返回一个新的String类对象.因此当把String类的引用传递给一个方法,该方法对String的任何改变,对原引用指向的对象没有任何影响,这一点和基本数据类型相似.
分解见图:

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

传值.jpg
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马