黑马程序员技术交流社区

标题: 用Object声明一个子类对象后打印方法为什么报错 [打印本页]

作者: 郭孟涛    时间: 2013-2-18 23:20
标题: 用Object声明一个子类对象后打印方法为什么报错
本帖最后由 郭孟涛 于 2013-2-19 18:31 编辑
  1. class ObjectDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Object ob = new Test(); // 这里用Object声明对象 ,object 作为一个父类为什么出错
  6.                 System.out.println(ob.talk()); // 这里打印为什么报错?上一句 用 Test 声明变量的时候没有错
  7.         }
  8. }
  9. class Test
  10. {
  11.         public int talk(){
  12.                 return 6;
  13.         }
  14. }
复制代码
下面这个示例,新建了一个子类,打印就正确
  1. class ObjectDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Test ob = new Test1(); //
  6.                 System.out.println(ob.talk()); // 这里打印正确
  7.         }
  8. }

  9. class Test
  10. {
  11.         public int talk(){
  12.                 return 6;
  13.         }
  14. }


  15. class Test1  extends Test
  16. {
  17.       
  18. }
复制代码

作者: 王昕    时间: 2013-2-18 23:39
因为左边是引用的类型,父类的引用可以指向子类的对象,Object类是所有类的父类,所以可以用Object类型的引用指向Test类型的对象。
但是引用调用对象的方法只能调用这种引用的类型自身就有的方法,因为编译器只知道你的ob是个Object类型的引用,不知道它指向的对象到底具体是什么类型。
如果你确实知道你的ob指向的是个Test类型的对象,那么可以用强制类型转换。把6行改成下面两行:
Test t = (Test) ob;
System.out.println(t.talk());
作者: 王昕    时间: 2013-2-19 00:54
那不叫建了一个子类,那叫声明了一个子类类型的引用,指向了子类的对象。
方法调用时,编译器看的是引用的类型,只能调用那个引用类型本身就带有的方法。
比如有父类Animal和它的子类Dog,Animal类定义了方法bark();,比如是让“喵喵”,Dog覆盖了bark();,改成“汪汪”。
Animal a = new Dog();
Dog d = new Dog();
a.bark();和d.bark();都是调用的Dog覆盖过的bark();,都会“汪汪”。
但是如果Animal没有定义bark();,那a.bark();就会报错,只能d.bark();。
编译看的是左边的引用类型,运行执行的是右边实际上的对象类型的方法。前提是左边的引用类型也有这个方法。
作者: Gaara    时间: 2013-2-19 01:16
你可能是这么认为的:
第一个例子里Object是Test的父类,调用talk方法时打印错误。
第二个例子里Test是Test1的父类,调用talk方法打印就对了。

但其实是不一样的因为Object里没有talk方法,所以在编译的时候就通过不了。(编译看左,运行看右)
而第二个方法相当于你把Test里的talk方法重写了。所以就通过了。

这么说可能更明白吧
你可以把第二个例子里的Test1中的talk方法的返回值变下,就清楚了。

作者: 郭孟涛    时间: 2013-2-19 01:32
张文彬 发表于 2013-2-19 01:16
你可能是这么认为的:
第一个例子里Object是Test的父类,调用talk方法时打印错误。
第二个例子里Test是Test ...

即使Talk()方法不覆写,一样编译通过
  1. class ObjectDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Test ob = new Test1(); //
  6.                 System.out.println(ob.talk()); // 这里打印正确
  7.         }
  8. }

  9. class Test
  10. {
  11.         public int talk(){
  12.                 return 6;
  13.         }
  14. }


  15. class Test1  extends Test
  16. {
  17.       
  18. }
复制代码

作者: Gaara    时间: 2013-2-19 01:51
郭孟涛 发表于 2013-2-19 01:32
即使Talk()方法不覆写,一样编译通过

那是因为你的父类Test里有talk方法啊。

你可以试试Test里没有talk方法。而Test1里有

编译肯定出错。

这跟我说的覆盖是一个意思就是说编译的时候要看左边有没有。然后运行的时候看右边运行
作者: 王钊    时间: 2013-2-19 17:56
兄弟,回头重点看继承多态这一块的视频。
Object ob = new Test(); 这是多态,ob是Object的引用,虽然指向子类对象,但只能调用Object所声明的方法。
Object没有声明talk()方法,所以编译就过不去。
例外,Object一共有11个方法,各个经典,建议学一下吧。




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