黑马程序员技术交流社区

标题: 对象赋值前后的去向和利用多态是否可同时引用的问题 [打印本页]

作者: 黄玉昆    时间: 2013-2-7 10:24
标题: 对象赋值前后的去向和利用多态是否可同时引用的问题
  1. <font size="1">class Person
  2. {
  3.    String name;
  4.    Person(String name)
  5.    {
  6.       this.name = name;
  7.    }
  8.    //...
  9. }
  10. //定义一个子类Student
  11. class Student extends Person
  12. {
  13.    String name;
  14.    private int id;
  15.         Student(String name,int id)
  16.         {
  17.                 super(name);
  18.                 this.id = id;
  19.         }
  20.         public int getId()
  21.         {
  22.                 return id;
  23.         }
  24.         public void setId(int id)
  25.         {
  26.                 this.id = id;
  27.         }

  28. }
  29. class DuotaiDemo
  30. {
  31.         public static void main(String[] args)
  32.         {
  33.                 //第一个
  34.                 Person p = new Person("小明");
  35.                 p = null;
  36.                 System.out.println(p);
  37.                 //----------------------
  38.                 //第二个
  39.                 //Person变量可以引用Person的对象,也可以引用它的子类对象
  40.                 Student stu = new Student("大明",0001);
  41.                 Person[] per = new Person[10];
  42.                 per[0] = stu;
  43.                 //第三个
  44.                 Student[] student = new Student[2];
  45.                 //将student转换成Person[]是合法的
  46.                 Person[] person = student;
  47.                 person[0] = new Person("小黑");//给person[0]赋Person类型的值
  48.                 student[0].setId(0002);
  49.                 System.out.println(student[0].name + "的id是" + student[0].getId());
  50.         }
  51. }</font>
复制代码
对于第一个:
将p = null,是p不再指向new出的“小明”这个对象了呢?还是说new出的这个“小明”也随之在内存中消亡了呢?还是说要等内存自动在某个时候消亡呢?
对于第二个:
我们说多态是表示事物的多种形态,那么,这里的多种形态,是不是不能同时具备呢?
上面的代码中,per[0] = stu后,它们引用的是同一个对象,是("大明",0001)这个对象,那么是不是Per[0]就不在指向new Person[10]其中的第一个对象(虽然为null)了呢?
对于第三个:
Person[] person = student;这个语句中,应该是指向的同一个类型的数组(应该是Person[]这个数组吧?),那么现在,student是Student[]数组的类型呢?还是Person[]数组的类型呢?
1、如果是Student[]数组的类型,那么下面的student[0].setId(0002);这个方法是没错的,但是就不是和Person[0]指向相同数组了,

是不是这时候已经将Person[] person = student;这句的行为覆盖掉了呢?
2、如果是Person[]数组的类型,那么下面的student[0].setId(0002);这个方法是不成立的,因为编译时虽然可以通过,但是运行后会报错,如下:

希望大家能帮忙解答清晰。


多态测试.png (5.08 KB, 下载次数: 75)

多态测试.png

作者: 王昕    时间: 2013-2-7 13:39
本帖最后由 王昕 于 2013-2-7 14:02 编辑

对于第一个:
将p = null,是p不再指向new出的“小明”这个对象了呢?还是说new出的这个“小明”也随之在内存中消亡了呢?还是说要等内存自动在某个时候消亡呢?
等到内存不够的时候会被垃圾收集器(GC)回收,不管什么时候被回收,反正你已经找不到它了,想用也用不到了,对你来说它已经挂了,只等内存不够被回收。
对于第二个:
我们说多态是表示事物的多种形态,那么,这里的多种形态,是不是不能同时具备呢?
上面的代码中,per[0] = stu后,它们引用的是同一个对象,是("大明",0001)这个对象,那么是不是Per[0]就不在指向new Person[10]其中的第一个对象(虽然为null)了呢?
多态主要用途是设定返回值类型,数组类型,参数类型的时候,可以用一种类型包涵多种子类型,方便代码重用和扩展。
数组就像杯架,变量就像杯子。引用就像遥控器,用来遥控对象。new Person[10]是一个对象,这个对象相当于一个杯架,上面有十个杯子,杯子里有十个遥控器,per[0]是第一个杯子,per[0]=stu 是让per[0]这个杯子里的遥控器,指向和stu这个遥控器相同的对象。杯子在杯架上的位置不会变,装的遥控器类型在声明的时候也已经定了,只能改变遥控器遥控的对象。
对于第三个:
Person[] person = student;这个语句中,应该是指向的同一个类型的数组(应该是Person[]这个数组吧?),那么现在,student是Student[]数组的类型呢?还是Person[]数组的类型呢?
1、如果是Student[]数组的类型,那么下面的student[0].setId(0002);这个方法是没错的,但是就不是和Person[0]指向相同数组了,
是不是这时候已经将Person[] person = student;这句的行为覆盖掉了呢?
2、如果是Person[]数组的类型,那么下面的student[0].setId(0002);这个方法是不成立的,因为编译时虽然可以通过,但是运行后会报错,如下:
希望大家能帮忙解答清晰。
这个语句是错的。
数组是个杯架,声明的时候,如果是Student[] student,那就是说,student遥控器指向的这个杯架上的杯子里面的遥控器,是遥控student类型对象的遥控器,如果是Person[] person,那么杯架上的杯子里就是遥控Person类型对象的遥控器。可是你的student这个遥控器,指向的是杯架(杯架就是数组,也是个对象),而不是Student对象,student[0]这种杯架上的杯子里的遥控器遥控的才是Student对象。遥控Person类型对象的遥控器可以指向Student类型的对象,但是指向杯架的遥控器是不兼容的。
你把Person[] person = student,这是不对的,因为person是个遥控杯架的遥控器(杯架上的杯子里装的是遥控Person的遥控器),student也是遥控杯架的,它俩杯架上的杯子装的不是一种遥控器,所以不能这样。遥控Person对象的遥控器可以指向Student对象,但是遥控杯架的遥控器类型不同不要赋值。
我们都是用遥控器(就是引用)来遥控对象的。父类的遥控器可以指向子类的对象,但是你的两种杯架Person[]和Student[]并不是继承关系,杯架上的杯子Penson[1]和Student[1]这种带下标的杯子里面的遥控器才是父子。数组是个对象,但是是个杯架,杯架的杯子里只装遥控器,也不装对象,可以装primitive类型。

作者: 黄玉昆    时间: 2013-2-7 14:49
王昕 发表于 2013-2-7 13:39
对于第一个:
将p = null,是p不再指向new出的“小明”这个对象了呢?还是说new出的这个“小明”也随之在内 ...

你的这个比喻,实在让我有些晕了。你说杯子里有十个遥控器,意思是说这个遥控器(引用)是在被子里(变量)里是不太对的,看下面的图(图1)就可是看出,不是这样的。你说“数组就像杯架,变量就像杯子。引用就像遥控器,用来遥控对象。”那对象比喻成什么了,遥控器遥控着什么呢?这三者没有一个是对象啊?(这里先不考虑万物皆对象这个说法啊)我觉得引用更像指针(也许不对)
对于第二个,你说"per[0]=stu 是让per[0]这个杯子里的遥控器,指向和stu这个遥控器相同的对象。”那么是不是就不指向new Person[10]中的对象了呢?
对于第三个,我觉得既然编译可以通过,这个“Person[] person = student”就是正确的,从现实生活中考虑的话,一个学生群体也是一个人群啊,那么将学生群体赋给人群,为什么就不行啊?

图1-内存.png (11.67 KB, 下载次数: 69)

内存

内存

作者: 王昕    时间: 2013-2-7 16:50
本帖最后由 王昕 于 2013-2-7 17:19 编辑

因为这是Head first Java上两三章的内容,而且书上有图。我没说杯子里有十个遥控器,一个杯子里只能有一个遥控器。
数组是对象,像杯架,它也生存在堆上,杯架不是杯子,数组里的每一个元素才是杯子,就像那种放鸡蛋的架子,有一个一个的格子。比如Student[10],这数组是个对象,生存在堆上,但是它不是十个Student对象,而是十个遥控器。new Person[10]没有建立任何Person对象,只建立了一个能放十个杯子的杯架而已。要建立Person对象必须是Person[0] = new Person();这样的才行(我只是举个无参数构造函数的例子,有参数的构造函数也行)。你图右边的对象你根本没建立起来,也不会给他分配空间,而且对象的值不会是null,引用的值才会是null,但是你这个引用是定义在方法里的,所以也没有初值,定义在类里的方法之外的引用才会自动赋初值。
作者: 王昕    时间: 2013-2-7 17:00
本帖最后由 王昕 于 2013-2-7 17:06 编辑

一个学生群体是个人群,但是你没有定义学生群是人群的子类,你只定义了学生是人的子类。学生群是人群,是这样的:
Person[] person = new Person[2];
Person[0] = new Student();
Person[1] = new Student();
Student是Person的子类没错,但是Student[]可不是Person[]的子类。Student[] student = new Student[10]这语句,右边是一个对象,只是个杯架而已,杯架上十个杯子,每个杯子一个遥控器,左边student也是个遥控器,是什么类型的遥控器?是Student[]类型的遥控器,遥控器是遥控对象的,右边对象是十个遥控器,不是十个Student对象。
你的问题主要在于,你认为new Student[10]可以建立十个Student对象,实际上没有,只建立了一个对象,这个对象就是杯架(带十个杯子十个遥控器),Student对象你还得再建。
引用是地址没错,但是对我们没用,我没没法用它做操纵对象以外的事,可以给它重新设指向的对象,但是类型得兼容。C语言里指针是个地址变量,数组名是地址常量,引用比数组名灵活一些,因为可以重新赋值,但是没有指针那么强大。
作者: 王昕    时间: 2013-2-7 17:08
本帖最后由 王昕 于 2013-2-7 17:10 编辑

你的图,把右边全删掉,把左边改成堆内存,就对了。new出来的东西就是对象,对象只能在堆上。你new出来的是左边,不过箭头还没指向任何东西,就是说你的遥控器还没配电视。等你给他赋值了就相当于设了电视给它。
作者: 朱玉玺    时间: 2013-2-7 18:14
图形说明最简单明了

多态demo0.jpg (61.92 KB, 下载次数: 70)

多态demo0.jpg

多态demo.jpg (125.57 KB, 下载次数: 51)

多态demo.jpg

作者: 朱玉玺    时间: 2013-2-7 18:42
本帖最后由 朱玉玺 于 2013-2-7 19:31 编辑
  1.   Person[] person = student;
复制代码
这句是合法的而且是有效的,这里person和student的区别是,person[index]只能调用父类的方法,不能调用student特有的方法;另外你子类的name隐藏了父类的name,所以你用子类的引用调用name的时候,永远都是null。
作者: 朱玉玺    时间: 2013-2-7 18:58
王昕 发表于 2013-2-7 13:39
对于第一个:
将p = null,是p不再指向new出的“小明”这个对象了呢?还是说new出的这个“小明”也随之在内 ...

对于说的第三点,Person[] person =student是错的这话不敢苟同
  1.   person[0] = new Student("小黑",005);//给person[0]赋Person类型的值
  2.                 student[0].setId(2);               
  3.                 System.out.println(student[0].name+student[0].getId());
复制代码

作者: 王昕    时间: 2013-2-7 19:55
本帖最后由 王昕 于 2013-2-7 19:56 编辑
朱玉玺 发表于 2013-2-7 18:58
对于说的第三点,Person[] person =student是错的这话不敢苟同


你写的代码是要说明什么?person[0]是Person类型的引用,当然可以赋Student对象给它,楼主的person是Person[]类型的引用,不是Person类型。
他的相当于Person[] person = new Student[10],这是对的?
作者: 朱玉玺    时间: 2013-2-7 20:13
王昕 发表于 2013-2-7 19:55
你写的代码是要说明什么?person[0]是Person类型的引用,当然可以赋Student对象给它,楼主的person是Pers ...

怎么不对,如果没有person=student这句,person能用person[0]这样表示吗,并利用person[0]对student[0]指向的对象进行改变吗?
作者: 王昕    时间: 2013-2-7 20:25
朱玉玺 发表于 2013-2-7 20:13
怎么不对,如果没有person=student这句,person能用person[0]这样表示吗,并利用person[0]对student[0]指 ...

你把你的代码加在那句后面,看看输出。我看了不对啊。
作者: 朱玉玺    时间: 2013-2-7 20:29
王昕 发表于 2013-2-7 20:25
你把你的代码加在那句后面,看看输出。我看了不对啊。

我知道,name为null是吧,这是因为Student的name隐藏了Person的name,而你在Student的name你调用的时候,永远都是null。把Student的name注释掉,你再试试。Person [] person = new Student[10],如果Person是一个接口的话,这不就是面向接口编程嘛
作者: 黄玉昆    时间: 2013-2-7 20:53
王昕 发表于 2013-2-7 16:50
因为这是Head first Java上两三章的内容,而且书上有图。我没说杯子里有十个遥控器,一个杯子里只能有一个 ...

我不太同意你的观点,
对于你说的数组是对象,生存在堆上,我同意,但是数组只是对象的集合,是将相同类型的对象集合在一起,但是他们是一个一个的实例,而不是一个整体,即使你不给他们赋值,他们一样有初始化状态,仍然是单个的,只不过是存放在一起了。而且new Student[10]确实是在内存中创建了十个对象,而且初始化值都为null,不信你可以自己测试下面的代码:
  1. class Demo0
  2. {
  3.     public static void main(String[] args)
  4.    {
  5.        Person[] p = new Person[10];
  6.        for (int i=0;i<p.length;i++)
  7.        {
  8.            System.out.println(p[i]);       
  9.        }
  10.   }
  11. }
  12. class Person
  13. {
  14.      String name;
  15.      Person(String name)
  16.     {
  17.      this.name = name;
  18.     }
  19. }
复制代码
你还说“而且对象的值不会是null,引用的值才会是null”,这也是不对的,因为引用在一定意义上来说是指针(虽然都说java中没有指针,但是其实是存在的,只不过和c语言中的不同罢了,具体你可以自己网上查查);再没赋值之前,对象(不是基本类型)的初始化值均为null。如果不清楚,你可以上网搜搜关于每种类型再没赋值前都是怎么样的状态。只要new了,它的状态就存在了。

作者: 黄玉昆    时间: 2013-2-7 21:15
本帖最后由 黄玉昆 于 2013-2-7 21:27 编辑
朱玉玺 发表于 2013-2-7 18:14
图形说明最简单明了

我觉得你这个第一个的赋值步骤是有点问题的,我个人觉得赋值应该这样:下图。
但是按理说第3步会在第5步之后是不存在的。但是此时就出现了一个问题,per[0]还是不是Person类型的呢?
如果是,但编译却是可以通过的,只是在运行的时候出现了我图中的那个错误:
Exception in thread "main" java.lang.ArrayStoreException: Person at DuotaiDemo.main<DuotaiDemo.java:48>,这就让人很郁闷了,难道问题仅仅是这出现的吗?
怎么会出现在第48行呢?不理解。

赋值步骤.png (160.3 KB, 下载次数: 68)

赋值步骤.png

作者: 朱玉玺    时间: 2013-2-7 21:25
黄玉昆 发表于 2013-2-7 20:53
我不太同意你的观点,
对于你说的数组是对象,生存在堆上,我同意,但是数组只是对象的集合,是将相同类 ...

“而且对象的值不会是null,引用的值才会是nul”这句话,我觉得没错,什么是对象,对象就相当于1,2,3这样的常量,null就相当于于数字中的0,你能说2的值是0吗?对象本身就是值,用于赋给引用变量,它没有值的这个概念。你把数组理解为对象的集合,其实我倒认为数组是引用的集合(基本数据类型除外),它本身并不是把所有的对象都放在虚拟机为他开辟的内存中,而是只把这些对象的引用放在为他开辟的内存中,需要使用某个元素时,它再通过引用去调取这个元素。
作者: 朱玉玺    时间: 2013-2-7 21:34
黄玉昆 发表于 2013-2-7 21:15
我觉得你这个第一个的赋值步骤是有点问题的,我个人觉得赋值应该这样:下图。
但是按理说第3步会在第5步之 ...

你把per[0]画在了栈内存中,其实它是在堆内存中的。试想,如果一个数组有十几万个元素,难道都这十几万个引用放在栈内存中?栈内存处理速度快,但空间有限啊
作者: 黄玉昆    时间: 2013-2-7 21:35
本帖最后由 黄玉昆 于 2013-2-7 21:44 编辑
朱玉玺 发表于 2013-2-7 21:25
“而且对象的值不会是null,引用的值才会是nul”这句话,我觉得没错,什么是对象,对象就相当于1,2,3这样 ...

他说的是对象的值(是值)不会是null,对象在默认初始化的时候,就是null,而引用怎么会是值呢?(我不是说像这种为了让对象消亡的语句: a = null),引用字面上就是指向,指向了这个地址,而像“a = null”这种语句,只是赋值而已,是将null的值赋给a,这个操作是为了让这个指向不再存在,而a这种引用是不会有值的。我的意思是:引用是中指向(相当于“指针”),是一个“行为”,而变量才有至值,a是一个变量而已啊。
作者: 黄玉昆    时间: 2013-2-7 21:37
朱玉玺 发表于 2013-2-7 21:34
你把per[0]画在了栈内存中,其实它是在堆内存中的。试想,如果一个数组有十几万个元素,难道都这十几万个 ...

数组与对象的内存分配方式相同。都是引用在栈,数据在堆。
作者: 朱玉玺    时间: 2013-2-7 21:44
黄玉昆 发表于 2013-2-7 21:35
他说的是对象的值(是值)不会是null,对象在默认初始化的时候,就是null,而引用怎么会是值呢?(我不是 ...

确切的说,是引用变量的初始化值是null,对象那里用初始化啊,按我的理解,对象就是一种特殊的常量。不太懂指针~:lol
作者: 王昕    时间: 2013-2-7 21:53
朱玉玺 发表于 2013-2-7 20:29
我知道,name为null是吧,这是因为Student的name隐藏了Person的name,而你在Student的name你调用的时候, ...

如果Person[] person = new Student[10]是对的,那么你打算给person[0]装什么东西呢?如果Person还有别的子类,比如Killer,那person[0]能指向Killer对象吗?
如果Person[] person = new Student[10],person[0]还是只能指向Student类型的话,那么别人不知道,会把Killer对象赋给person[0],那就错了。
如果person[0]能指向所有Person类型的子类型的话,那直接Person[] person = new Person[10]。
Person[] person = new Person[10],Person[0] = new Student(),是多态,用父类的数组元素指向子类的对象,Person[] person = new Student[10]这种东西有任何意义吗?把它声明成Person[]就是为了让别人知道,它的元素是指向Person类型及其子类型的,左边是Person[],右边是Student[10],这是为了干嘛?
作者: 王昕    时间: 2013-2-7 22:05
黄玉昆 发表于 2013-2-7 20:53
我不太同意你的观点,
对于你说的数组是对象,生存在堆上,我同意,但是数组只是对象的集合,是将相同类 ...

哥们,你好像没区分什么是对象,什么是对象的引用,引用有的翻译成句柄。
你的p是引用而不是对象,如果用指针来解释的话,把引用看成指针,对象是指针指向的那一坨东西。你可能认为p.XXX能调用到对象的成员,所以它是对象,可是它还是引用,正因为他是个遥控器,用“.”就相当于按下了遥控器上的按钮,然后对象就被遥控器操作了。这不是我的观点,书上都这么写的。new Student[10],是建立了十个引用,对象没有建。你如果还不信,那我也没办法了。
Student对象只能这样建:new Student();要想一次建很多Student,只能用循环一个一个建。
作者: 朱玉玺    时间: 2013-2-7 22:09
王昕 发表于 2013-2-7 21:53
如果Person[] person = new Student[10]是对的,那么你打算给person[0]装什么东西呢?如果Person还有别的 ...

你说的确实对。但没意义归没意义,你不能说它错啊:lol
作者: 王昕    时间: 2013-2-7 22:12
黄玉昆 发表于 2013-2-7 21:35
他说的是对象的值(是值)不会是null,对象在默认初始化的时候,就是null,而引用怎么会是值呢?(我不是 ...

对象是一大坨东西,不是一个值,无从谈起是不是null,只有引用(reference)才能是null。
作者: 王昕    时间: 2013-2-7 22:19
黄玉昆 发表于 2013-2-7 21:37
数组与对象的内存分配方式相同。都是引用在栈,数据在堆。

哥们,你基本概念有误区。
引用可以在栈也可以在堆,像Student[] stu = new Student[10]这种吧,stu在栈,stu[1],stu[2]这种都在堆。new Student[10]就是十个引用绑在一起作为一个对象。new一下只能建一个对象,这个语句new出来的对象占的内存的大小是十个引用的大小,所有引用占的字节都是一样多的。而new Student();建的才是一个学生对象,学生对象有多大,那可就没准了。
作者: 王昕    时间: 2013-2-7 22:24
朱玉玺 发表于 2013-2-7 22:09
你说的确实对。但没意义归没意义,你不能说它错啊

我都不说编译运行有没有错的问题,那其实是不严重的问题。大家一起写程序,你写个Person[] p=new Student[10],我和你合作,我一看p是个Person[]类型,我往里装它的子类,比如Killer,会发生什么?
而且这个运行确实没有有意义的结果。这种建数组对象,左边是什么右边肯定也是什么的,因为右边本来就是为左边服务的。:handshake
作者: 黄玉昆    时间: 2013-2-7 22:25
王昕 发表于 2013-2-7 22:12
对象是一大坨东西,不是一个值,无从谈起是不是null,只有引用(reference)才能是null。 ...

这“一大坨东西”是什么意思啊?怎么会不关null的事呢?
作者: 黄玉昆    时间: 2013-2-7 22:28
王昕 发表于 2013-2-7 22:19
哥们,你基本概念有误区。
引用可以在栈也可以在堆,像Student[] stu = new Student[10]这种吧,stu在栈 ...

不知道给你写的那个代码,你运行了没有,你运行之后就知道,我就用了一个new,但是打印了十个null
  1. class Demo0
  2. {
  3.     public static void main(String[] args)
  4.    {
  5.        Person[] p = new Person[10];
  6.        for (int i=0;i<p.length;i++)
  7.        {
  8.            System.out.println(p[i]);        
  9.        }
  10.   }
  11. }
  12. class Person
  13. {
  14.      String name;
  15.      Person(String name)
  16.     {
  17.      this.name = name;
  18.     }
  19. }
复制代码

作者: 王昕    时间: 2013-2-7 22:31
黄玉昆 发表于 2013-2-7 22:25
这“一大坨东西”是什么意思啊?怎么会不关null的事呢?


就是说一个Student对象有什么,得看你写类的时候给他了多少成员变量,才能知道这坨东西有什么,有多大。
而引用,就占那么多字节 ,就是个遥控器。遥控器啥也不遥控的时候就是null,有东西遥控就是那个东西的地址。null是什么?null就是一个引用的特殊值,就是没有。对象只能说对象的某个成员变量是不是null,前提是这个变量是个引用类型。
作者: 朱玉玺    时间: 2013-2-7 22:31
王昕 发表于 2013-2-7 22:24
我都不说编译运行有没有错的问题,那其实是不严重的问题。大家一起写程序,你写个Person[] p=new Student ...

呵呵,也只有在楼主这样的实验中,一般不会出现这种情况。
作者: 黄玉昆    时间: 2013-2-7 22:34
王昕 发表于 2013-2-7 22:24
我都不说编译运行有没有错的问题,那其实是不严重的问题。大家一起写程序,你写个Person[] p=new Student ...

我不是为了说明这段代码是不是有意义,只是为了把内存分配问题搞清楚。只有内存中的状态清楚了,才能更好地理解代码,更好地运行代码。尤其在数组这种特殊的对象,还有一种类型就是String,也是很特殊的,我觉得能把这两个弄清楚,就基本上把类型性的知识学透彻了。这是我的本意。
作者: 王昕    时间: 2013-2-7 22:35
黄玉昆 发表于 2013-2-7 22:28
不知道给你写的那个代码,你运行了没有,你运行之后就知道,我就用了一个new,但是打印了十个null ...

我知道你一个new打印十个null啊,因为你new出来了十个绑在一起的引用啊。
十个绑在一起的引用是一个数组对象。
作者: 黄玉昆    时间: 2013-2-7 22:37
王昕 发表于 2013-2-7 22:05
哥们,你好像没区分什么是对象,什么是对象的引用,引用有的翻译成句柄。
你的p是引用而不是对象,如果用 ...

我不是不信,既然都说服不了对方,那么就用很有权威性的证据说明一下,就行了。等我看到了相关的知识再交流。不过很谢谢你的回复。从你的回复中,确实学到了不少东西,十分感谢你
作者: 王昕    时间: 2013-2-7 22:37
本帖最后由 王昕 于 2013-2-7 22:39 编辑
朱玉玺 发表于 2013-2-7 22:31
呵呵,也只有在楼主这样的实验中,一般不会出现这种情况。


你没用person[1]. 这种来调用对象,我认为这样用的话是会出异常的。你用的都是student[1]. 。
作者: 朱玉玺    时间: 2013-2-7 22:40
王昕 发表于 2013-2-7 22:37
你没用person[1]. 这种来调用对象,我认为这样用的话是会出异常的。你用的都是student[1]. 。 ...

用person的话,只能调name,不能掉id,因为这个引用看不到子类的id
作者: 王昕    时间: 2013-2-7 22:47
黄玉昆 发表于 2013-2-7 22:37
我不是不信,既然都说服不了对方,那么就用很有权威性的证据说明一下,就行了。等我看到了相关的知识再交 ...

嗯,畅销书还是比较权威的吧……你看看Head first Java第三章还是第四章记不清了,就知道了,还有后面多态的大概七八九章吧。
不用客气,你回复我认真,我自然回复你也认真,如果你表现的对我的说法不屑,我肯定也就不理啦:lol
你回我那么多是想帮我纠正我的错误,是想帮助我,虽然关于引用这个问题我比较有把握是我对了,不过以后别的问题就另当别论了。多交流总是好的,交流无所谓谁对谁错,一起学习,交流只要真诚就好,你的回复我觉得很真诚,所以我也想帮你搞清楚。引用是个遥控器这个比喻,很多书都用,包括Thinking in Java。
作者: 王昕    时间: 2013-2-7 22:52
朱玉玺 发表于 2013-2-7 22:40
用person的话,只能调name,不能掉id,因为这个引用看不到子类的id

有Person[] person = new Student[2];这种语句存在,并且有person[0] = new 随便();这种存在,用person[0].能输出正确的信息?
作者: 朱玉玺    时间: 2013-2-7 23:12
只能new Student
作者: 黄玉昆    时间: 2013-2-7 23:23
王昕 发表于 2013-2-7 21:53
如果Person[] person = new Student[10]是对的,那么你打算给person[0]装什么东西呢?如果Person还有别的 ...

你可以看看我新改的代码。结果会返回一个错误,是空指针异常,但是这个错我,我看了相关的文章,说是“空指针异常发生在对象为空,但是引用这个对象的方法。”。这说明,还是有对象存在的,只不过为空。
代码如下:
  1. class Demo0
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Student[] s = new Student[10];
  6.                 for (int i=0;i<s.length;i++)
  7.                 {
  8.                         s[i].name = (String)("a " + i);
  9.                         s[i].setId(i);
  10.                         System.out.println(s[i].name + "的ID:" + s[i].getId());       
  11.                 }
  12.         }
  13. }

  14. class Student
  15. {
  16.         String name;
  17.         private int id;
  18.         Student(String name,int id)
  19.         {
  20.                 this.name = name;
  21.                 this.id = id;
  22.         }
  23.         public int getId()
  24.         {
  25.                 return id;
  26.         }
  27.         public void setId(int id)
  28.         {
  29.                 this.id = id;
  30.         }

  31. }
复制代码

作者: 黄玉昆    时间: 2013-2-7 23:28
王昕 发表于 2013-2-7 22:47
嗯,畅销书还是比较权威的吧……你看看Head first Java第三章还是第四章记不清了,就知道了,还有后面多 ...

嗯啊,你说的挺对的,不过你也可以看看java核心技术,里面关于对象中继承那部分,有关多态的知识。资料我分享在了帖子里,希望能对你有帮助。
资料:http://bbs.itheima.com/thread-37948-1-1.html
作者: 王昕    时间: 2013-2-7 23:46
本帖最后由 王昕 于 2013-2-7 23:49 编辑
黄玉昆 发表于 2013-2-7 23:23
你可以看看我新改的代码。结果会返回一个错误,是空指针异常,但是这个错我,我看了相关的文章,说是“空 ...


他其实想表达的意思是:“空指针异常发生在reference为null,但是用这个引用调用对象的方法。”
有时候翻译的人不分对象和引用,把reference翻译成对象,很容易误导人,因为C++里面Student s;这种语句就说成定义Student类型的对象s,但是Java还是说对象引用s,或者说引用s。
Java核心技术卷I是京京工作室翻译的,翻译毁了,卷II翻译的比较好。
包括Head first Java,中文版翻译的也是不大行,所以得有个英文的对着看。中文的百度文库有,英文的csdn有。
作者: 黄玉昆    时间: 2013-2-7 23:48
王昕 发表于 2013-2-7 23:46
他其实想表达的意思是:“空指针异常发生在reference为null,但是用这个引用调用对象的方法。”
有时候翻 ...

忘了给你文章地址了:http://blog.csdn.net/wangkr111/article/details/7830079
作者: 王昕    时间: 2013-2-7 23:54
黄玉昆 发表于 2013-2-7 23:48
忘了给你文章地址了:http://blog.csdn.net/wangkr111/article/details/7830079

Head first Java 60页,就是讲建Dog数组对象和建Dog对象。百度文库一搜就有的。
http://wenku.baidu.com/view/4b0ff1d8d15abe23482f4d8a.html
作者: 王昕    时间: 2013-2-8 00:03
黄玉昆 发表于 2013-2-7 23:48
忘了给你文章地址了:http://blog.csdn.net/wangkr111/article/details/7830079

2:空指针异常发生在对象为空,但是引用这个对象的方法。例如: String s = null; //对象s为空(null) int length = s.length();//发生空指针异常

3:一个变量是null,及只有其名,没有实值内容,也没分配内存,当你要去取他的长度,对他进行操作就会出现NullPointException,所以生命一个变量时最好给它分配好内存空间,给予赋值。

这个人可能是先学的C++习惯了C++的说法。String s;他管 s 叫对象严格来说不合适。
他的3,其实就是说,一个引用是null,他说“只有其名”,就是说只有引用,“没有实质内容,也没分配内存”,就说没有new出来一个对象,他说“声明一个变量最好给它分配好内存空间”,就说让你声明的时候就new出来,不要只声明一个引用类型,而不给它new一个对象。
他写博客用词不会抠那么仔细,你看都有错别字,声明写成了“生命”。
对于老手管引用叫对象无所谓,他心里知道就行了,新手真的会以为是个对象。
可能你是觉得String s = "abc";没有new也有对象,所以 s 是对象,这句其实是String s = new String("abc");
作者: 王昕    时间: 2013-2-8 00:05
引用这个叫法,也不是太好,因为“引用”说话的时候经常会用到,也许真的是引用的意思而不是reference,所以有翻译叫“句柄”。
作者: 黄玉昆    时间: 2013-2-8 00:15
王昕 发表于 2013-2-8 00:05
引用这个叫法,也不是太好,因为“引用”说话的时候经常会用到,也许真的是引用的意思而不是reference,所 ...

嗯,或许这怎么说是不太好,但是既然是公认叫法,就只能这样了。




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