黑马程序员技术交流社区

标题: 给大家出一道练习题 [打印本页]

作者: 戴振良    时间: 2013-1-24 14:37
标题: 给大家出一道练习题
本帖最后由 戴振良 于 2013-1-28 15:11 编辑

        黑马的发展可真快啊,感觉才毕业没多久,17届都有了,黑马真是强!!!
        好久没来论坛逛了,很多东西要学习的,现在感觉上班挺好的,没什么压力,上班时间还可以学习。我以前看的基础视频是张孝详老师的,后来才知道老毕的基础视频讲的比较牛,最近我也在看老毕的基础视频了,老毕真是神人也,讲课也太好了,要问到目前为止我觉得讲课最厉害的,当属老毕了,虽然他没有亲自教过我。看了老毕画的内存图,感觉很清析,后来我自己也画了个,贴出来给大家看看对不对。
        学弟学妹们为进黑马都很努力哈,以前听说老有人抱怨积分难赚,在这里我也给大家个赚积分的机会吧,在后面有两个练习,大家可以试着把内存图画出来,对你理解对象的赋值传参都肯定大有收益,只要你画出来了,我相信 版主肯定会给积分的。而且我这有许多金币,看谁画对的我给他奖励些金币,不只道系统允许给多少。现在这东西好似可以在积分商城买东西了。

下面是我画的内存分析图:
class Person { }
class QuoteDemo {
   public static void newPerson(Person p) {
      p = new Person();
   }
   public static void main(String[] args) {
      Person p = null;
      newPerson(p);
      System.out.println(p);// 此处打印:null
   }  
}
代码从main方法开始执行:
1Person p = null; 执行后的内存图:

2newPerson(p); 调用newPerson方法时在栈内存又生成了一个newPerson方法中的变量p

3newPerson(p); 这里把main方法中的p的值传给了newPerson方法中的p,所以此时newPerson方法中的p也指向了null

4p = new Person();执行newPerson 方法中的代码后内存图:
5newPerson方法执行完后继续执行main方法中的代码:System.out.println(p); 这里打印的pmain方法中的p,所以打印结果为:null


听说字符串也算是对象,也是在堆内存中分配的,看下面例子:
  1. import java.util.ArrayList;

  2. public class Demo {
  3.         public static void main(String[] args) {
  4.                 ArrayList<String> al = fun();
  5.                 String s = al.get(0);
  6.                 System.out.println(s);
  7.         }
  8.         
  9.         public static ArrayList<String> fun(){
  10.                 ArrayList<String> al = new ArrayList<String>();
  11.                 String s = "张三" ;
  12.                 al.add(s);
  13.                 s = "李四";
  14.                 return al;
  15.         }
  16. }
复制代码
运行后,打印结果是:  张三

再看下面例子:
  1. class Person {
  2.         String name;
  3. }

  4. class QuoteDemo {
  5.         public static void newPerson(Person p) {
  6.                 p = new Person();
  7.         }
  8.         public static void main(String[] args) {
  9.                 ArrayList<Person> al = fun();
  10.                 Person p = al.get(0);
  11.                 System.out.println(p.name);
  12.         }        
  13.         
  14.         public static ArrayList<Person> fun(){
  15.                 ArrayList<Person> al = new ArrayList<Person>();
  16.                 Person p = new Person();
  17.                 p.name = "张三";
  18.                 al.add(p);
  19.                 p.name = "李四";
  20.                 return al;
  21.         }
  22. }
复制代码
运行后,打印结果是:  李四



作者: 李培根    时间: 2013-1-24 14:44
支持学长来了
作者: jonn    时间: 2013-1-24 14:48
{:soso_e105:}我要去....顶学长....
作者: 金鑫    时间: 2013-1-24 14:53
希望学长以后能有时间多回来转转,给学习学妹们多多传授经验
作者: 戴振良    时间: 2013-1-24 15:10
金鑫 发表于 2013-1-24 14:53
希望学长以后能有时间多回来转转,给学习学妹们多多传授经验

还没奖给别人金币呢,我就赚了几十金币了:lol
金鑫你不是我们班的吗?我记得我们九期好像有一个同学叫金鑫~~~
作者: 贾文泽    时间: 2013-1-24 15:58
不晓得准不准确,望指点
第一题,输出  “张三”   画的不好看,额



捕获.PNG (24.72 KB, 下载次数: 80)

捕获.PNG

作者: 黄嵘才    时间: 2013-1-24 16:53

1.ArrayList<String> al = fun();//调用的方法返回一个引用地址,类型是一个集合。此条没有开避内存空间
//执行方法fun
2.ArrayList<String> al = new ArrayList<String>();//开避一个空间a1,用作集合存放   只收 <String>  假定地址:0111
3.String s = "张三" ;                al.add(s);
                s = "李四";

//s指向堆中的“张三”(如果没有张三,就new张三再指向)。
//空间a1加入元素“张三”
//s重指向堆中“李四”(如果没有李四,就new李四再指向)。
4.return al;//返回引用,即将地址:0111,给赋 main中的a1.

5.
String s = al.get(0);
                System.out.println(s);

//获取集合中第一个元素,打印到控制台。

1.png (12.72 KB, 下载次数: 64)

1.png

1.png (12.72 KB, 下载次数: 68)

1.png

作者: 周志强    时间: 2013-1-24 17:39
学长 以后要常来啊  加油  

看看 我画的 怎样?

1.png (53.44 KB, 下载次数: 70)

1.png

2.png (73.07 KB, 下载次数: 75)

2.png

作者: 李培根    时间: 2013-1-24 18:22
学长的金币可以去换个u盘下做纪念了。
作者: 金鑫    时间: 2013-1-24 18:32
{:soso_e113:}学长第一个内存分析图的例子也有一定迷惑性的,估计应该有人第一时间怀疑怎么会是null的吧
作者: 黄锦成    时间: 2013-1-24 19:08
我也来做一下,师兄,指导一下啊

test1.PNG (19.48 KB, 下载次数: 78)

这是第一题的

这是第一题的

test2.PNG (20.26 KB, 下载次数: 76)

这是第二题的

这是第二题的

作者: 王少雷    时间: 2013-1-24 19:30
话说,我怎么就不会看图呢~{:soso_e101:}
作者: walkonby    时间: 2013-1-24 20:21
疑惑的是不知道 第二个 person 类中的 name属性在堆中有没有单独的一块空间?

复件 内存图1.jpg (1.03 MB, 下载次数: 84)

复件 内存图1.jpg

内存图2.jpg (1.03 MB, 下载次数: 71)

内存图2.jpg

作者: txl    时间: 2013-1-24 20:40
本帖最后由 黑马唐贤来 于 2013-1-24 20:44 编辑

第一张弄出来啦
{:soso_e134:}

QQ截图20130124204325.png (62.86 KB, 下载次数: 64)

QQ截图20130124204325.png

作者: 梁俊    时间: 2013-1-24 20:59
都是高手啊
作者: 胡勇敏    时间: 2013-1-24 21:29
学长发帖 必须支持下。话说回来了 老毕的基础视频真不是盖的。相当好,基础的标杆啊。
作者: 耿文达    时间: 2013-1-24 21:32
顶学长,向学长学习!{:soso_e129:}
作者: 黄锦成    时间: 2013-1-24 23:24
周志强 发表于 2013-1-24 17:39
学长 以后要常来啊  加油  

看看 我画的 怎样?

点评有个数限制,直接回复了:第一个图画得可以,最好要分清两个方法中的al,第二个图中,Person在内存中只有一个对象,你弄成了两个了
作者: 黄锦成    时间: 2013-1-24 23:27
王少雷 发表于 2013-1-24 19:30
话说,我怎么就不会看图呢~

这个要多看毕老师画内存图的视频,分清楚值类型和引用类型在内存中的情况
作者: 黄锦成    时间: 2013-1-24 23:30
本帖最后由 黄锦成 于 2013-1-24 23:31 编辑
黑马唐贤来 发表于 2013-1-24 20:40
第一张弄出来啦


不错。可以完善一下,例如s指向了李四,指向张三的线可以加个叉。
建议你继续把第二张图画出来
作者: 黄锦成    时间: 2013-1-24 23:37
esirong 发表于 2013-1-24 16:53
1.ArrayList al = fun();//调用的方法返回一个引用地址,类型是一个集合。此条没有开避内存空间
//执行方 ...

//s指向堆中的“张三”(如果没有张三,就new张三再指向)。
//空间a1加入元素“张三”
//s重指向堆中“李四”(如果没有李四,就new李四再指向)。

s不是指向堆中的,而是常量池中的,要经过new的那些才在堆内存中。还有,画图时,尽量从栈指向堆,这样比较好看点,你画这个图看起来有点怪怪的。虽然说做人是要有自己的个性,但是要给别人看的东西,按照普遍的做法比较好
作者: 贾文泽    时间: 2013-1-25 06:05
刚睡醒,额,顺便把第二题做了,先感谢版主对我上面画的第一题指点,下面是第二题,有不对的地方还望指点


捕获0000.PNG (37.38 KB, 下载次数: 35)

捕获0000.PNG

作者: 黄锦成    时间: 2013-1-25 10:28
张政 发表于 2013-1-24 20:21
疑惑的是不知道 第二个 person 类中的 name属性在堆中有没有单独的一块空间?
...

看明白你的图了。
我对你画的图给一些意见:第一张图:s是放在常量池中,最好画一个单独的区域,还有s=al.get(0)放在栈这边来;第二张:堆中的new Person 和 堆中的p相隔太远了些,要紧靠一起,更能说明他们之间的关系
作者: Just_Only    时间: 2013-1-25 10:35
都是好厉害的啊
作者: 黄锦成    时间: 2013-1-25 10:38
梁俊 发表于 2013-1-24 20:59
都是高手啊

来画一下,这个是老毕基础面向对象内的知识。
作者: 戴振良    时间: 2013-1-25 10:55
金鑫 发表于 2013-1-24 18:32
学长第一个内存分析图的例子也有一定迷惑性的,估计应该有人第一时间怀疑怎么会是null的吧 ...

仔细看了我们9期的群,是有个叫金兴,跟你同音,呵呵。
你说的迷惑性,或许是有的吧,因为我当时就是遇到了这个问题的,然后听说传基本类型的变量时,方法中是改变不了外面的变量,而传引用变量时,方法中是可以改变方法外的变量的,当时就觉得p是个引用变量啊,怎么没改变呢,后来想起老毕讲的画内存分析才知道了原因。
作者: 鲁柯    时间: 2013-1-25 10:55
画的有些乱,怕大家看不懂,添加了文字注解

内存图.JPG (53.39 KB, 下载次数: 39)

内存图

内存图

作者: 戴振良    时间: 2013-1-25 11:06
看了大家画的图,都有那么些意思了,不管对与不对,敢于动手画并贴上来的兄弟姐妹们,说明你们的上进心是很强的,善于分析,动手能力也强,学好Java不成问题。当然,我没仔细看,因为差不多都是一张图画出来,不容易看清楚思路,希望大家可以分步骤来截图,这样不会的人也可以很轻松的看懂,如果是一张图,我想时间自己久了,我估计自己看着也有点乱呢。
作者: 黄锦成    时间: 2013-1-25 11:09
IC-月辰 发表于 2013-1-25 06:05
刚睡醒,额,顺便把第二题做了,先感谢版主对我上面画的第一题指点,下面是第二题,有不对的地方还望指点

...

main中的al拉个箭头指向堆内存的0x0000,这样子更能一目了然了
作者: 黄锦成    时间: 2013-1-25 11:17
鲁柯 发表于 2013-1-25 10:55
画的有些乱,怕大家看不懂,添加了文字注解

就是d这一步骤注释有点小错误,其他都没问题。d那里你说:将s指向另一个字符串“李四”,则集合中的元素的元素s的指向跟着改变。我说一下我对这一步的理解:
al.add(s);是将s的引用放到集合中,后面的栈中的s指向“李四”,与集合中的没有任何关系了,此时集合中的第一个元素保存的还是“张三”的引用
作者: 周志强    时间: 2013-1-25 11:19
黄锦成 发表于 2013-1-24 23:24
点评有个数限制,直接回复了:第一个图画得可以,最好要分清两个方法中的al,第二个图中,Person在内存中 ...

谢谢了   我会改正的  谢谢 版主  和学长
作者: 鲁柯    时间: 2013-1-25 11:26
再来一道吧,练练手,大家指点指点

内存图00.JPG (56.4 KB, 下载次数: 35)

内存图00.JPG

作者: 丁强强    时间: 2013-1-25 15:22
哥们不是毕业了吗,还返回头看基础的?
作者: 戴振良    时间: 2013-1-26 13:19
丁强强 发表于 2013-1-25 15:22
哥们不是毕业了吗,还返回头看基础的?

老毕的课讲的那么好,不看一下可惜了!
作者: 杨剑    时间: 2013-2-1 11:49
第一道题的详细过程

作者: 戴振良    时间: 2013-2-4 10:01
杨剑 发表于 2013-2-1 11:49
第一道题的详细过程

看你理解的也差不多了,但感觉还没理解透,看:http://bbs.itheima.com/thread-37276-1-1.html,看第3楼第4楼是这道题的答案。
作者: 秦_奋    时间: 2014-12-9 18:37
支持学长!!!!




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